Compare commits

...

40 Commits

Author SHA1 Message Date
Tim
e386d3ee21 Merge branch 'dev' 2015-09-14 20:53:09 +02:00
Tim
285946bf94 v1.1.9
Close href tag on activity pane.
Update program description.
2015-09-14 20:45:49 +02:00
drzoidberg33
578ba52215 Merge pull request #185 from JonnyWong16/miscellaneous-fixes
Add tracks to user recently watched
2015-09-14 20:23:05 +02:00
Jonathan Wong
5126c39c26 Group recently watched tracks together by album
* Also group identical movie or episode
2015-09-14 00:02:31 -07:00
Jonathan Wong
5ec9e41244 Add tracks to user recently watched
* Clean up poster styles to match info pages
2015-09-13 23:28:42 -07:00
Tim
5eebf6592a Make music items clickable in activity pane now that we have info pages. 2015-09-14 01:09:12 +02:00
Tim
7994351644 Fix broken history logging. 2015-09-14 00:58:28 +02:00
drzoidberg33
e445228b8a Merge pull request #182 from JonnyWong16/music-info-pages
Music info pages
2015-09-13 23:42:54 +02:00
drzoidberg33
46e6250329 Merge pull request #183 from JonnyWong16/miscellaneous-fixes
Fix typo for location of PMS logs path
2015-09-13 23:28:23 +02:00
Jonathan Wong
2edfc1e3da Add link to music info from recently added 2015-09-13 14:09:22 -07:00
Jonathan Wong
f2024b0854 Fix typo for location of PMS logs path 2015-09-13 14:04:20 -07:00
Jonathan Wong
5f2cf6cb7a Add links for track items on tables 2015-09-13 13:33:09 -07:00
Jonathan Wong
73664b6a03 Update info page to show music info 2015-09-13 13:32:44 -07:00
Jonathan Wong
af131ce16d Change code to get generic library children items
* Merge the separate season list and episode list
2015-09-13 13:31:51 -07:00
Jonathan Wong
414c4c2ffa Add artist, album, and track metadata 2015-09-13 13:29:04 -07:00
drzoidberg33
d2cdc2cea2 Merge pull request #180 from JonnyWong16/miscellaneous-fixes
Add photos to current activity
2015-09-13 20:09:26 +02:00
Jonathan Wong
b860f9a5e8 Add photos to current activity
* Also fix BIF fade in
2015-09-12 23:09:01 -07:00
drzoidberg33
e5535b6167 Merge pull request #177 from JonnyWong16/miscellaneous-fixes
Fix paused time on graphs and other miscellaneous items
2015-09-13 01:44:46 +02:00
Jonathan Wong
6359c02c80 Fix PMS Token input error message on settings page 2015-09-11 21:17:11 -07:00
Jonathan Wong
1c589fbefa Change season and episode number in history table item title
* For seasons/episodes of any number of digits
2015-09-11 21:09:48 -07:00
Jonathan Wong
b768ad8a19 Fix Mystery platform names in graphs 2015-09-11 17:41:25 -07:00
Jonathan Wong
60878ed12e Add table name session_history to paused_counter in watch stats query 2015-09-11 15:40:24 -07:00
Jonathan Wong
328d744efd Swap order of History and Users in the navbar 2015-09-11 15:19:30 -07:00
Jonathan Wong
92a868c3c6 Clean up watch statistics duration database queries 2015-09-11 13:35:50 -07:00
Jonathan Wong
7b9210a5fc Add music to graphs
* Separate out TV, movies, and music on bar graphs
* Separate out direct play, direct stream, and transcode on bar graphs
2015-09-11 13:12:33 -07:00
Jonathan Wong
fb872596d6 Fix paused time from graphs 2015-09-11 11:11:32 -07:00
Jonathan Wong
a43efef28a Fix write session to history only if library item
Some channel items, specifically Apple movie trailers, are counted as
movie items. Make sure the rating_key is a number to filter these out.
2015-09-10 21:30:34 -07:00
Jonathan Wong
e30e6dfe35 Fix Plex Web click through logo 2015-09-10 15:03:38 -07:00
Tim
eaadd5e2d6 Merge branch 'dev' 2015-09-09 22:20:45 +02:00
Tim
c608c7c9fc v1.1.8 2015-09-09 22:19:59 +02:00
drzoidberg33
451485d706 Merge pull request #173 from JonnyWong16/miscellaneous-fixes
Change Plex click through to app.plex.tv instead of local IP
2015-09-09 22:16:05 +02:00
Jonathan Wong
849675185d Change Plex click through to app.plex.tv instead of local IP 2015-09-09 13:13:17 -07:00
drzoidberg33
b060a23733 Merge pull request #170 from JonnyWong16/miscellaneous-fixes
Miscellaneous
2015-09-09 21:51:11 +02:00
drzoidberg33
bee9091182 Add Gitter Button to README 2015-09-09 16:49:28 +02:00
Jonathan Wong
f8e1ba6798 Add link to poster on info pages to view item in Plex/Web 2015-09-09 02:13:52 -07:00
Tim
e5ce57fead Fix bug with missing tagline field in PlexWatch db import. 2015-09-08 21:30:09 +02:00
Jonathan Wong
c9e2d1d200 Fix delete mode on info pages 2015-09-08 10:35:33 -07:00
Jonathan Wong
88b6eae3bf Add platform icons for windows and windows phone 2015-09-08 09:09:16 -07:00
drzoidberg33
c7d6ee8021 Merge pull request #166 from JonnyWong16/miscellaneous-fixes
Fix home stats title overflow
2015-09-08 00:44:26 +02:00
Jonathan Wong
7480508af2 Fix home stats title overflow 2015-09-07 15:38:34 -07:00
37 changed files with 1445 additions and 865 deletions

View File

@@ -1,5 +1,27 @@
# Changelog
## v1.1.9 (2015-09-14)
* Another JonnyWong release. I'm going to stop thanking you now ;)
* Add music plays to graphs.
* Add info pages for music items.
* Add music to user recently watched items.
* Add photo views to Activity pane (photos are not logged).
* Fix token validation message on Settings page.
* Fix some "Mystery" platform names.
* Fix paused time be counted for graph data.
* Other small bug fixes.
## v1.1.8 (2015-09-09)
* Add platform images for Windows devices. Thanks @JonnyWong.
* Add click-through to PlexWeb preplay page from info page. Thanks @JonnyWong.
* Fix broken delete option on info pages. Thanks @JonnyWong.
* Fix tagline bug in PlexWatch db import tool.
* Fix home stats text overflow bug. Thanks @JonnyWong.
## v1.1.7 (2015-09-07)
* Show tagline in info screens for movies. Thanks @JonnyWong.

View File

@@ -64,7 +64,7 @@ def main():
# Set up and gather command line arguments
parser = argparse.ArgumentParser(
description='Python frontend for PlexWatch.')
description='A Python based monitoring and tracking tool for Plex Media Server.')
parser.add_argument(
'-v', '--verbose', action='store_true', help='Increase console logging verbosity')

View File

@@ -1,5 +1,7 @@
#PlexPy
[![Join the chat at https://gitter.im/drzoidberg33/plexpy](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/drzoidberg33/plexpy?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
A python based web application for monitoring, analytics and notifications for Plex Media Server (www.plex.tv).
This project is based on code from Headphones (https://github.com/rembo10/headphones) and PlexWatchWeb (https://github.com/ecleese/plexWatchWeb).
@@ -120,4 +122,4 @@ If you **comply with these rules** you can [post your request/issue](http://gith
## License
This is free software under the GPL v3 open source license. Feel free to do with it what you wish, but any modification must be open sourced. A copy of the license is included.
This software includes Highsoft software libraries which you may freely distribute for non-commercial use. Commerical users must licence this software, for more information visit https://shop.highsoft.com/faq/non-commercial#non-commercial-redistribution.
This software includes Highsoft software libraries which you may freely distribute for non-commercial use. Commerical users must licence this software, for more information visit https://shop.highsoft.com/faq/non-commercial#non-commercial-redistribution.

View File

@@ -62,16 +62,16 @@ from plexpy import version
% else:
<li><a href="home"><i class="fa fa-lg fa-home"></i></a></li>
% endif
% if title=="History":
<li class="active"><a href="history">History</a></li>
% else:
<li><a href="history">History</a></li>
% endif
% if title=="Users" or title=="User":
<li class="active"><a href="users">Users</a></li>
% else:
<li><a href="users">Users</a></li>
% endif
% if title=="History":
<li class="active"><a href="history">History</a></li>
% else:
<li><a href="history">History</a></li>
% endif
% if title=="Graphs":
<li class="active"><a href="graphs">Graphs</a></li>
% else:

View File

@@ -778,36 +778,88 @@ a .dashboard-activity-metadata-user-thumb:hover {
font-weight: bold;
color: #F9AA03;
}
/*.dashboard-activity-instance-overlay {
position: relative;
top: -12px;
text-align: left;
height: 53px;
width: 250px;
border-radius: 0 0 3px 3px;
}*/
.dashboard-recent-media-row {
width: 100%;
margin:0 auto;
text-align: center;
position: relative;
z-index: 0;
}
.dashboard-recent-media {
width: 100%;
margin: auto;
list-style: none;
}
.dashboard-recent-media-instance {
}
.dashboard-recent-media li {
margin-right: 27px;
float: left;
position: relative;
left: 0px;
margin-right: 25px;
margin-bottom: 25px;
}
.dashboard-recent-media-poster {
position: relative;
float: left;
min-height: 340px;
}
.dashboard-recent-media-cover {
position: relative;
margin-top: 75px;
float: left;
}
a:hover .dashboard-recent-media-poster,
a:hover .dashboard-recent-media-cover {
webkit-box-shadow: inset 0 0 0 2px #e9a049;
-moz-box-shadow: inset 0 0 0 2px #e9a049;
box-shadow: inset 0 0 0 2px #e9a049;
}
.dashboard-recent-media-poster-face {
background-position: center;
background-size: cover;
height: 225px;
width: 150px;
position: relative;
-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);
z-index: -2;
}
.dashboard-recent-media-cover-face {
background-position: center;
background-size: cover;
height: 150px;
width: 150px;
position: relative;
-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);
z-index: -2;
}
.dashboard-recent-media-overlay {
position: absolute;
left: 0;
right: 0;
bottom: 0;
text-align: left;
background: -moz-linear-gradient(top, rgba(0,0,0,0) 30%, rgba(0,0,0,1) 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(30%,rgba(0,0,0,0)), color-stop(100%,rgba(0,0,0,1)));
background: -webkit-linear-gradient(top, rgba(0,0,0,0) 30%,rgba(0,0,0,1) 100%);
background: -o-linear-gradient(top, rgba(0,0,0,0) 30%,rgba(0,0,0,1) 100%);
background: -ms-linear-gradient(top, rgba(0,0,0,0) 30%,rgba(0,0,0,1) 100%);
background: linear-gradient(to bottom, rgba(0,0,0,0) 30%,rgba(0,0,0,1) 100%);
height: 100%;
z-index: -1;
}
.dashboard-recent-media-overlay-text {
color: #aaa;
font-size: 12px;
float: left;
position: absolute;
left: 8px;
bottom: 5px;
}
.dashboard-recent-media-metacontainer {
width: 150px;
font-size: 13px;
margin-bottom: 20px;
clear: both;
}
.dashboard-recent-media-metacontainer h3 {
@@ -825,6 +877,9 @@ a .dashboard-activity-metadata-user-thumb:hover {
text-align: left;
clear: both;
}
.dashboard-recent-media-metacontainer h3.text-muted {
color: #777;
}
.dashboard-recent-media-metacontainer .text-muted {
padding: 5px 3px 0 3px;
text-overflow: ellipsis;
@@ -876,10 +931,12 @@ a .dashboard-activity-metadata-user-thumb:hover {
.summary-navbar-list {
padding: 0 25px;
color: #999;
white-space: nowrap;
overflow: hidden;
}
.summary-navbar-list span {
float: left;
margin-right: 20px;
display: inline-block;
margin-right: 15px;
}
.summary-navbar-list span a {
color: #999;
@@ -904,6 +961,10 @@ a .dashboard-activity-metadata-user-thumb:hover {
line-height: 40px;
float: left;
clear: left;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
width: 100%;
}
.summary-content-title h1 a {
color: #F9AA03;
@@ -920,6 +981,10 @@ a .dashboard-activity-metadata-user-thumb:hover {
line-height: 40px;
float: left;
clear: left;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
width: 100%;
}
.summary-content-title h3 {
margin-top: 0;
@@ -927,7 +992,9 @@ a .dashboard-activity-metadata-user-thumb:hover {
color: #999;
font-size: 28px;
line-height: 40px;
float: right;
position: absolute;
bottom: 0;
right: 0;
}
.summary-content-title h3 a:hover {
text-decoration: underline;
@@ -973,11 +1040,54 @@ a .dashboard-activity-metadata-user-thumb:hover {
overflow: hidden;
z-index: 1;
}
a .summary-poster-face:hover,
a .summary-poster-face-episode:hover {
.summary-poster-face-track {
background-position: center;
background-size: cover;
height: 250px;
width: 250px;
position: relative;
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);
overflow: hidden;
z-index: 1;
}
.summary-poster-face-overlay {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-image: -webkit-gradient(linear,left 0,left 100%,from(rgba(0,0,0,.7)),to(rgba(0,0,0,.9)));
background-image: -webkit-linear-gradient(top,rgba(0,0,0,.7),0,rgba(0,0,0,.9),100%);
background-image: -moz-linear-gradient(top,rgba(0,0,0,.7) 0,rgba(0,0,0,.9) 100%);
background-image: linear-gradient(to bottom,rgba(0,0,0,.7) 0,rgba(0,0,0,.9) 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#b3000000', endColorstr='#e6000000', GradientType=0);
webkit-box-shadow: inset 0 0 0 2px #e9a049;
-moz-box-shadow: inset 0 0 0 2px #e9a049;
box-shadow: inset 0 0 0 2px #e9a049;
opacity: 0;
transition: opacity .2s;
}
.summary-poster-face-overlay span {
display: block;
width: 100%;
height: 100%;
background-image: url(../images/plex-logo-light.svg);
background-size: 100px;
background-repeat: no-repeat;
background-position: center;
opacity: 0;
transition: opacity .3s;
}
a:hover .summary-poster-face .summary-poster-face-overlay,
a:hover .summary-poster-face-episode .summary-poster-face-overlay,
a:hover .summary-poster-face-track .summary-poster-face-overlay,
a:hover .summary-poster-face .summary-poster-face-overlay span,
a:hover .summary-poster-face-episode .summary-poster-face-overlay span,
a:hover .summary-poster-face-track .summary-poster-face-overlay span {
opacity: 1;
}
.summary-content-padding {
float: left;
@@ -998,47 +1108,11 @@ a .summary-poster-face-episode:hover {
position: relative;
float: left;
}
.summary-content-director {
.summary-content-details-tag {
float: left;
line-height: 24px;
}
.summary-content-director strong {
color: #fff;
margin-left: 2px;
margin-right: 10px;
}
.summary-content-studio {
float: left;
line-height: 24px;
}
.summary-content-studio strong {
color: #fff;
margin-left: 2px;
margin-right: 10px;
}
.summary-content-airdate {
float: left;
line-height: 24px;
}
.summary-content-airdate strong {
color: #fff;
margin-left: 2px;
margin-right: 10px;
}
.summary-content-duration {
float: left;
line-height: 24px;
}
.summary-content-duration strong {
color: #fff;
margin-left: 2px;
margin-right: 10px;
}
.summary-content-content-rating {
float: left;
line-height: 24px;
}
.summary-content-content-rating strong {
.summary-content-details-tag strong {
color: #fff;
margin-left: 2px;
margin-right: 10px;
@@ -1145,135 +1219,57 @@ a .summary-poster-face-episode:hover {
background-size: contain;
height: 16px;
}
.show-seasons-wrapper {
.item-children-wrapper {
}
.show-seasons-instance {
.item-children-instance {
list-style: none;
margin: 0;
}
.show-seasons-instance li {
.item-children-instance li {
float: left;
position: relative;
left: 0px;
margin-right: 25px;
margin-bottom: 25px;
}
a .show-seasons-card-overlay:hover {
.item-children-instance li.item-children-list-item {
width: 100%;
height: 35px;
margin-right: 0;
margin-bottom: 0;
}
.item-children-poster {
float: left;
position: relative;
left: 0px;
}
a:hover .item-children-poster {
webkit-box-shadow: inset 0 0 0 2px #e9a049;
-moz-box-shadow: inset 0 0 0 2px #e9a049;
box-shadow: inset 0 0 0 2px #e9a049;
}
.show-seasons-poster {
float: left;
position: relative;
left: 0px;
}
.show-seasons-card-overlay {
position: absolute;
left: 0;
right: 0;
bottom: 0;
text-align: left;
background: -moz-linear-gradient(top, rgba(0,0,0,0) 30%, rgba(0,0,0,1) 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(30%,rgba(0,0,0,0)), color-stop(100%,rgba(0,0,0,1)));
background: -webkit-linear-gradient(top, rgba(0,0,0,0) 30%,rgba(0,0,0,1) 100%);
background: -o-linear-gradient(top, rgba(0,0,0,0) 30%,rgba(0,0,0,1) 100%);
background: -ms-linear-gradient(top, rgba(0,0,0,0) 30%,rgba(0,0,0,1) 100%);
background: linear-gradient(to bottom, rgba(0,0,0,0) 30%,rgba(0,0,0,1) 100%);
height: 225px;
}
.show-seasons-overlay-text {
color: #aaa;
font-size: 12px;
float: left;
position: absolute;
left: 8px;
bottom: 5px;
}
.show-seasons-instance-text-wrapper {
width: 150px;
font-size: 13px;
margin-bottom: 20px;
clear: both;
}
.show-seasons-instance-text-wrapper h3 {
padding: 5px 3px 0 3px;
color: #fff;
text-overflow: ellipsis;
overflow: hidden;
position: relative;
font-size: 13px;
margin: 0;
line-height: 15px;
font-weight: normal;
width: 250px;
white-space: nowrap;
text-align: left;
clear: both;
}
.show-seasons-title a {
text-decoration: none;
font-size: 14px;
font-weight: normal;
color: #fff;
float: left;
text-overflow: ellipsis;
overflow: hidden;
position: relative;
white-space: nowrap;
width: 205px;
margin-top: 2px;
margin-left: 0px;
margin-bottom: 20px;
}
.show-seasons a:hover {
color: #F9AA03;
}
.season-episodes-wrapper {
}
.season-episodes-instance {
list-style: none;
margin: 0;
}
.season-episodes-instance li {
float: left;
position: relative;
left: 0px;
margin-right: 25px;
margin-bottom: 25px;
}
a .season-episodes-card-overlay:hover {
-webkit-box-shadow: inset 0 0 0 2px #e9a049;
-moz-box-shadow: inset 0 0 0 2px #e9a049;
box-shadow: inset 0 0 0 2px #e9a049;
}
.season-episodes-poster {
float: left;
position: relative;
left: 0px;
}
.season-episodes-poster-face {
.item-children-poster-face {
background-position: center;
background-size: cover;
height: 140px;
width: 250px;
position: relative;
-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);
z-index: -2;
}
.season-episodes-poster-face img {
bottom: 0;
overflow: hidden;
.item-children-poster-face.season-poster {
width: 150px;
height: 225px;
}
.item-children-poster-face.episode-poster {
width: 250px;
height: 140px;
}
.season-episodes-poster-face img:hover {
-webkit-box-shadow: 0 0 0 2px #F9AA03;
-moz-box-shadow: 0 0 0 2px #F9AA03;
box-shadow: 0 0 0 2px #F9AA03;
.item-children-poster-face.album-poster {
width: 150px;
height: 150px;
}
.season-episodes-card-overlay {
.item-children-card-overlay {
position: absolute;
left: 0;
right: 0;
@@ -1285,14 +1281,10 @@ a .season-episodes-card-overlay:hover {
background: -o-linear-gradient(top, rgba(0,0,0,0) 30%,rgba(0,0,0,1) 100%);
background: -ms-linear-gradient(top, rgba(0,0,0,0) 30%,rgba(0,0,0,1) 100%);
background: linear-gradient(to bottom, rgba(0,0,0,0) 30%,rgba(0,0,0,1) 100%);
height: 140px;
height: 100%;
z-index: -1;
}
.season-episodes-card-overlay-index {
color: #fff;
font-size: 11px;
text-shadow: 0 1px 5px rgba(0,0,0,0.2);
}
.season-episodes-overlay-text {
.item-children-overlay-text {
color: #aaa;
font-size: 12px;
float: left;
@@ -1300,7 +1292,22 @@ a .season-episodes-card-overlay:hover {
left: 8px;
bottom: 5px;
}
.season-episodes-instance-text-wrapper h3 {
.item-children-instance-text-wrapper {
font-size: 13px;
margin-bottom: 20px;
clear: both;
}
.item-children-instance-text-wrapper.season-item {
width: 150px;
}
.item-children-instance-text-wrapper.episode-item {
width: 250px;
}
.item-children-instance-text-wrapper.album-item {
width: 150px;
}
.item-children-instance-text-wrapper h3 {
width: 100%;
padding: 5px 3px 0 3px;
color: #fff;
text-overflow: ellipsis;
@@ -1310,36 +1317,52 @@ a .season-episodes-card-overlay:hover {
margin: 0;
line-height: 15px;
font-weight: normal;
width: 250px;
white-space: nowrap;
text-align: left;
clear: both;
}
.season-episodes-title a {
text-decoration: none;
font-size: 14px;
font-weight: normal;
color: #fff;
.item-children-list-item-odd {
border-top: 0px solid #343434;
border-bottom: 0px solid #343434;
background-color: rgba(255,255,255,0.010);
height: 100%;
font-size: 13px;
padding-top: 10px;
}
.item-children-list-item-even {
border-top: 0px solid #343434;
border-bottom: 0px solid #343434;
background-color: rgba(255,255,255,0.035);
height: 100%;
font-size: 13px;
padding-top: 10px;
}
.item-children-list-item-odd:hover,
.item-children-list-item-even:hover {
background-color: rgba(255,255,255,0.075);
}
.item-children-list-item-index {
float: left;
color: #777;
text-align: right;
display: inline-block;
width: 35px;
margin-right: 10px;
}
.item-children-list-item-title {
display: inline-block;
width: calc(100% - 110px);
text-overflow: ellipsis;
overflow: hidden;
position: relative;
white-space: nowrap;
width: 205px;
margin-top: 2px;
margin-left: 0px;
margin-bottom: 20px;
}
.season-episodes a:hover {
color: #F9AA03;
}
.season-episodes-season {
color: #aaa;
font-size: 12px;
float: left;
position: absolute;
left: 8px;
bottom: 5px;
.item-children-list-item-duration {
float: right;
color: #777;
text-align: right;
display: inline-block;
width: 40px;
margin-right: 20px;
}
.settings-alert {
float: left;
@@ -1581,6 +1604,7 @@ a .season-episodes-card-overlay:hover {
display: inline-block;
position: relative;
padding: 6px 0 0 20px;
max-width: 100%;
}
.home-platforms-instance-playcount h4 {
font-size: 14px;

View File

@@ -67,7 +67,7 @@ DOCUMENTATION :: END
% if data['stream_count'] != '0':
% for a in data['sessions']:
<div class="dashboard-instance" id="instance-${a['session_key']}">
% if a['type'] == 'movie' or a['type'] == 'episode':
% if a['type'] == 'movie' or a['type'] == 'episode' or a['type'] == 'track':
<a href="info?item_id=${a['rating_key']}">
% endif
<div class="dashboard-activity-poster">
@@ -93,6 +93,8 @@ DOCUMENTATION :: END
<div class="dashboard-activity-poster-face" style="background-image: url(pms_image_proxy?img=${a['thumb']}&width=500&height=280);"></div>
% endif
% endif
% elif a['type'] == 'photo':
<div class="dashboard-activity-poster-face bif" style="background-image: url(pms_image_proxy?img=${a['thumb']}&width=500&height=500);"></div>
% else:
<div class="dashboard-activity-cover-face" style="background-image: url(pms_image_proxy?img=${a['thumb']}&width=300&height=300&fallback=cover);"></div>
% endif
@@ -160,17 +162,31 @@ DOCUMENTATION :: END
% elif a['audio_decision'] == 'transcode':
Audio &nbsp;<strong>Transcode (${a['transcode_audio_codec']}) (${a['transcode_audio_channels']}ch)</strong>
% endif
% elif a['type'] == 'photo':
% if a['video_decision'] == 'direct play':
Stream &nbsp;<strong>Direct Play</strong>
% else:
Stream &nbsp;<strong>
Transcoding
(Speed: ${a['transcode_speed']})
% if a['throttled'] == '1':
(Throttled)
% endif
</strong>
% endif
% endif
<br>
</div>
</div>
% if a['type'] != 'photo':
<div class="dashboard-activity-poster-info-bar">
<div class="dashboard-activity-poster-info-time">
<span class="progress_time">${a['progress']}</span>/<span class="progress_time">${a['duration']}</span>
</div>
</div>
% endif
</div>
% if a['type'] == 'movie' or a['type'] == 'episode':
% if a['type'] == 'movie' or a['type'] == 'episode' or a['type'] == 'track':
</a>
% endif
<div class="dashboard-activity-progress">
@@ -198,9 +214,11 @@ DOCUMENTATION :: END
% elif a['type'] == 'clip':
${a['title']}
% elif a['type'] == 'track':
${a['grandparent_title']} - ${a['title']}
<a href="info?item_id=${a['rating_key']}">${a['grandparent_title']} - ${a['title']}</a>
% elif a['type'] == 'photo':
${a['parent_title']}
% else:
${a['grandparent_title']} - ${a['title']}
${a['title']}
% endif
</div>
<div class="dashboard-activity-metadata-subtitle">
@@ -209,7 +227,9 @@ DOCUMENTATION :: END
% elif a['type'] == 'movie':
${a['year']}
% elif a['type'] == 'track':
${a['parent_title']}
<a href="info?item_id=${a['parent_rating_key']}">${a['parent_title']}</a>
% elif a['type'] == 'photo':
${a['title']}
% else:
${a['year']}
% endif
@@ -231,7 +251,7 @@ DOCUMENTATION :: END
<script>
// When using bif indexes make the image transition a little smoother.
$('.bif').each(function() {
$(this).fadeIn(1000);
$(this).hide().fadeIn(1000);
});
// Convert timestamps to readable times

View File

@@ -48,7 +48,7 @@
<div class="col-md-12">
<h4><i class="fa fa-history"></i> Daily <span class="yaxis-text">Play count</span> <small>Last <span class="days">30</span> days</small></h4>
<p class="help-block">
The total play count or duration of movies and tv played per day. Click a graph point to open up a list of items played for that specific date.
The total play count or duration of tv, movies, and music played per day. Click a graph point to open up a list of items played for that specific date.
</p>
<div class="graphs-instance">
<div class="watch-chart" id="chart_div_plays_by_day">
@@ -62,7 +62,7 @@
<div class="col-md-6">
<h4><i class="fa fa-calendar"></i> <span class="yaxis-text">Play count</span> by day of week <small>Last <span class="days">30</span> days</small></h4>
<p class="help-block">
The combined total of movies and tv played per day of the week.
The combined total of tv, movies, and music played per day of the week.
</p>
<div class="graphs-instance">
<div class="watch-chart" id="chart_div_plays_by_dayofweek" style="float: left;">
@@ -75,7 +75,7 @@
<div class="col-md-6">
<h4><i class="fa fa-clock-o"></i> <span class="yaxis-text">Play count</span> by hour of day <small>Last <span class="days">30</span> days</small></h4>
<p class="help-block">
The combined total of movies and tv played per hour of the day.
The combined total of tv, movies, and music played per hour of the day.
</p>
<div class="graphs-instance">
<div class="watch-chart" id="chart_div_plays_by_hourofday">
@@ -90,7 +90,7 @@
<div class="col-md-6">
<h4><i class="fa fa-television"></i> <span class="yaxis-text">Play count</span> by top 10 platforms <small>Last <span class="days">30</span> days</small></h4>
<p class="help-block">
The combined total of movies and tv played by top 10 most active platforms.
The combined total of tv, movies, and music played by top 10 most active platforms.
</p>
<div class="graphs-instance">
<div class="watch-chart" id="chart_div_plays_by_platform" style="float: left;">
@@ -103,7 +103,7 @@
<div class="col-md-6">
<h4><i class="fa fa-user"></i> <span class="yaxis-text">Play count</span> by top 10 users <small>Last <span class="days">30</span> days</small></h4>
<p class="help-block">
The combined total of movies and tv played by top 10 most active users.
The combined total of tv, movies, and music played by top 10 most active users.
</p>
<div class="graphs-instance">
<div class="watch-chart" id="chart_div_plays_by_user">
@@ -121,7 +121,7 @@
<div class="col-md-12">
<h4><i class="fa fa-video-camera"></i> Daily Stream type breakdown <small>Last <span class="days">30</span> days</small></h4>
<p class="help-block">
The total play count or duration of movies and tv by the transcode decision. Click a graph point to open up a list of items played for that specific date.
The total play count or duration of tv, movies, and music by the transcode decision. Click a graph point to open up a list of items played for that specific date.
</p>
<div class="graphs-instance">
<div class="watch-chart" id="chart_div_plays_by_stream_type">
@@ -135,7 +135,7 @@
<div class="col-md-6">
<h4><i class="fa fa-expand"></i> <span class="yaxis-text">Play count</span> by source resolution <small>Last <span class="days">30</span> days</small></h4>
<p class="help-block">
The combined total of movies and tv by their original resolution (pre-transcoding).
The combined total of tv and movies by their original resolution (pre-transcoding).
</p>
<div class="graphs-instance">
<div class="watch-chart" id="chart_div_plays_by_source_resolution" style="float: left;">
@@ -148,7 +148,7 @@
<div class="col-md-6">
<h4><i class="fa fa-expand"></i> <span class="yaxis-text">Play count</span> by stream resolution <small>Last <span class="days">30</span> days</small></h4>
<p class="help-block">
The combined total of movies and tv by their streamed resolution (post-transcoding).
The combined total of tv and movies by their streamed resolution (post-transcoding).
</p>
<div class="graphs-instance">
<div class="watch-chart" id="chart_div_plays_by_stream_resolution">
@@ -163,7 +163,7 @@
<div class="col-md-6">
<h4><i class="fa fa-television"></i> <span class="yaxis-text">Play count</span> by platform and stream type <small>Last <span class="days">30</span> days</small></h4>
<p class="help-block">
The combined total of movies and tv by platform and stream type.
The combined total of tv, movies, and music by platform and stream type.
</p>
<div class="graphs-instance">
<div class="watch-chart" id="chart_div_plays_by_platform_by_stream_type" style="float: left;">
@@ -176,7 +176,7 @@
<div class="col-md-6">
<h4><i class="fa fa-user"></i> <span class="yaxis-text">Play count</span> by user and stream type <small>Last <span class="days">30</span> days</small></h4>
<p class="help-block">
The combined total of movies and tv by user and stream type.
The combined total of tv, movies, and music by user and stream type.
</p>
<div class="graphs-instance">
<div class="watch-chart" id="chart_div_plays_by_user_by_stream_type" style="float: left;">
@@ -194,7 +194,7 @@
<div class="col-md-12">
<h4><i class="fa fa-calendar"></i> Plays by Month <small>Last 12 months</small></h4>
<p class="help-block">
The combined total of movies and tv by month.
The combined total of tv, movies, and music by month.
</p>
<div class="graphs-instance">
<div class="watch-chart" id="chart_div_plays_by_month">

View File

@@ -51,16 +51,17 @@ DOCUMENTATION :: END
from plexpy import helpers
# Human readable duration
def hd(minutes):
if int(minutes) > 60:
hours = int(helpers.cast_to_float(minutes) / 60)
minutes = int(helpers.cast_to_float(minutes) % 60 )
def hd(seconds):
minutes = helpers.cast_to_float(seconds) / 60
if minutes > 60:
hours = int(minutes / 60)
minutes = int(minutes % 60)
if minutes > 0:
return "<h3>" + str(hours) + "</h3><p>hrs</p><h3>" + str(minutes) + "</h3><p>mins</p>"
else:
return "<h3>" + str(hours) + "</h3><p>hrs</p>"
else:
return "<h3>" + minutes + "</h3><p>mins</p>"
return "<h3>" + str(int(minutes)) + "</h3><p>mins</p>"
%>
% if data:

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="3086px" height="1000px" viewBox="0 0 3086 1000" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.2.2 (9983) - http://www.bohemiancoding.com/sketch -->
<title>plex-logo-light</title>
<desc>Created with Sketch.</desc>
<defs>
<radialGradient cx="89.2670157%" cy="49.76%" fx="89.2670157%" fy="49.76%" r="92.4996161%" id="radialGradient-1">
<stop stop-color="#F9BE03" offset="0%"></stop>
<stop stop-color="#CC7C19" offset="100%"></stop>
</radialGradient>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="plex-logo-light" sketch:type="MSArtboardGroup">
<g sketch:type="MSLayerGroup">
<path d="M3085.99,0 L2795.989,0 L2505.99,500 L2795.989,1000 L3085.737,1000 L2795.989,500.25 L3085.99,0" id="X" fill="#FFFFFF" sketch:type="MSShapeGroup"></path>
<path d="M2186,0 L2476.00071,0 L2796,500.25 L2476.00071,1000.5 L2186,1000.5 L2505.99929,500.25 L2186,0" id="chevron" fill="url(#radialGradient-1)" sketch:type="MSShapeGroup"></path>
<path d="M2085.947,1000 L1508.874,1000 L1508.874,0 L2085.947,0 L2085.947,173.737 L1721.339,173.737 L1721.339,393.299 L2060.594,393.299 L2060.594,567.03 L1721.339,567.03 L1721.339,824.895 L2085.947,824.895 L2085.947,1000" id="E" fill="#FFFFFF" sketch:type="MSShapeGroup"></path>
<path d="M791.276,1000 L791.276,0 L1003.316,0 L1003.316,824.895 L1408.925,824.895 L1408.925,1000 L791.276,1000" id="L" fill="#FFFFFF" sketch:type="MSShapeGroup"></path>
<g id="P" fill="#FFFFFF" sketch:type="MSShapeGroup">
<path d="M589.947,558.824 C522.679,615.831 427.037,644.325 303.009,644.325 L212.04,644.325 L212.04,1000 L0,1000 L0,643.947829 L0,470.337388 L290,470.697418 C467.563171,468.627777 476.842468,359.878967 476.842468,322.200012 C476.842468,287.221283 476.842468,175.445374 319,173.699997 L0,173.703242 L0,0 L319.424,0 C440.717,0 532.939,26.107 596.101,78.321 C659.253,130.534 690.834,208.392 690.834,311.902 C690.834,419.527 657.202,501.83 589.947,558.824 Z" id="Path"></path>
<rect id="Path" x="0" y="110" width="212.2" height="429"></rect>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@@ -61,19 +61,37 @@ DOCUMENTATION :: END
<span><i class="fa fa-chevron-right"></i></span>
<span><a href="#">${data['title']}</a></span>
% elif data['type'] == 'season':
<span>TV Shows</span>
<span><i class="fa fa-chevron-right"></i></span>
<span class="hidden-xs hidden-sm">TV Shows</span>
<span class="hidden-xs hidden-sm"><i class="fa fa-chevron-right"></i></span>
<span><a href="info?item_id=${data['parent_rating_key']}">${data['parent_title']}</a></span>
<span><i class="fa fa-chevron-right"></i></span>
<span><a href="#">Season ${data['index']}</a></span>
% elif data['type'] == 'episode':
<span>TV Shows</span>
<span><i class="fa fa-chevron-right"></i></span>
<span><a href="info?item_id=${data['grandparent_rating_key']}">${data['grandparent_title']}</a></span>
<span><i class="fa fa-chevron-right"></i></span>
<span class="hidden-xs hidden-sm">TV Shows</span>
<span class="hidden-xs hidden-sm"><i class="fa fa-chevron-right"></i></span>
<span class="hidden-xs hidden-sm"><a href="info?item_id=${data['grandparent_rating_key']}">${data['grandparent_title']}</a></span>
<span class="hidden-xs hidden-sm"><i class="fa fa-chevron-right"></i></span>
<span><a href="info?item_id=${data['parent_rating_key']}">Season ${data['parent_index']}</a></span>
<span><i class="fa fa-chevron-right"></i></span>
<span><a href="#">Episode ${data['index']} - ${data['title']}</a></span>
% elif data['type'] == 'artist':
<span>Music</span>
<span><i class="fa fa-chevron-right"></i></span>
<span><a href="#">${data['title']}</a></span>
% elif data['type'] == 'album':
<span class="hidden-xs hidden-sm">Music</span>
<span class="hidden-xs hidden-sm"><i class="fa fa-chevron-right"></i></span>
<span><a href="info?item_id=${data['parent_rating_key']}">${data['parent_title']}</a></span>
<span><i class="fa fa-chevron-right"></i></span>
<span><a href="#">${data['title']}</a></span>
% elif data['type'] == 'track':
<span class="hidden-xs hidden-sm">Music</span>
<span class="hidden-xs hidden-sm"><i class="fa fa-chevron-right"></i></span>
<span class="hidden-xs hidden-sm"><a href="info?item_id=${data['grandparent_rating_key']}">${data['grandparent_title']}</a></span>
<span class="hidden-xs hidden-sm"><i class="fa fa-chevron-right"></i></span>
<span><a href="info?item_id=${data['parent_rating_key']}">${data['parent_title']}</a></span>
<span><i class="fa fa-chevron-right"></i></span>
<span><a href="#">Track ${data['index']} - ${data['title']}</a></span>
% endif
</div>
</div>
@@ -81,16 +99,34 @@ DOCUMENTATION :: END
<div class="summary-content-title-wrapper">
<div class="col-md-9">
<div class="summary-content-poster hidden-xs hidden-sm">
% if data['type'] == 'episode':
<div class="summary-poster-face-episode" style="background-image: url(pms_image_proxy?img=${data['thumb']}&width=500&height=280&fallback=poster);"></div>
% elif data['type'] == 'season':
<div class="summary-poster-face" style="background-image: url(pms_image_proxy?img=${data['thumb']}&width=300&height=450&fallback=poster);"></div>
% if data['type'] == 'track':
<a href="http://app.plex.tv/web/app#!/server/${config['pms_identifier']}/details/%2Flibrary%2Fmetadata%2F${data['parent_rating_key']}" target="Plex/Web" title="View in Plex/Web">
% else:
<div class="summary-poster-face" style="background-image: url(pms_image_proxy?img=${data['thumb']}&width=300&height=450&fallback=poster);"></div>
<a href="http://app.plex.tv/web/app#!/server/${config['pms_identifier']}/details/%2Flibrary%2Fmetadata%2F${data['rating_key']}" target="Plex/Web" title="View in Plex/Web">
% endif
% if data['type'] == 'episode':
<div class="summary-poster-face-episode" style="background-image: url(pms_image_proxy?img=${data['thumb']}&width=500&height=280&fallback=poster);">
<div class="summary-poster-face-overlay">
<span></span>
</div>
</div>
% elif data['type'] == 'artist' or data['type'] == 'album' or data['type'] == 'track':
<div class="summary-poster-face-track" style="background-image: url(pms_image_proxy?img=${data['thumb']}&width=500&height=500&fallback=poster);">
<div class="summary-poster-face-overlay">
<span></span>
</div>
</div>
% else:
<div class="summary-poster-face" style="background-image: url(pms_image_proxy?img=${data['thumb']}&width=300&height=450&fallback=poster);">
<div class="summary-poster-face-overlay">
<span></span>
</div>
</div>
% endif
</a>
</div>
<div class="summary-content-title">
% if data['type'] == 'movie' or data['type'] == 'show':
% if data['type'] == 'movie' or data['type'] == 'show' or data['type'] == 'artist':
<h1>&nbsp;</h1><h1>${data['title']}</h1>
% elif data['type'] == 'season':
<h1>&nbsp;</h1><h1><a href="info?item_id=${data['parent_rating_key']}">${data['parent_title']}</a></h1>
@@ -99,6 +135,13 @@ DOCUMENTATION :: END
<h1><a href="info?item_id=${data['grandparent_rating_key']}">${data['grandparent_title']}</a></h1>
<h2>${data['title']}</h2>
<h3 class="hidden-xs">S${data['parent_index']} &middot; E${data['index']}</h3>
% elif data['type'] == 'album':
<h1><a href="info?item_id=${data['parent_rating_key']}">${data['parent_title']}</a></h1>
<h2>${data['title']}</h2>
% elif data['type'] == 'track':
<h1><a href="info?item_id=${data['grandparent_rating_key']}">${data['grandparent_title']}</a></h1>
<h2><a href="info?item_id=${data['parent_rating_key']}">${data['parent_title']}</a> - ${data['title']}</h2>
<h3 class="hidden-xs">T${data['index']}</h3>
% endif
</div>
</div>
@@ -107,44 +150,52 @@ DOCUMENTATION :: END
<div class="col-md-9">
% if data['type'] == 'movie' or data['type'] == 'show' or data['type'] == 'season':
<div class="summary-content-padding hidden-xs hidden-sm" style="height: 275px;"></div>
% elif data['type'] == 'episode':
<div class="summary-content-padding hidden-xs hidden-sm" style="height: 40px;"></div>
% elif data['type'] == 'artist' or data['type'] == 'album' or data['type'] == 'track':
<div class="summary-content-padding hidden-xs hidden-sm" style="height: 150px;"></div>
% else:
<div class="summary-content-padding hidden-xs hidden-sm"></div>
% endif
<div class="summary-content">
<div class="summary-content-details-wrapper">
% if (data['type'] == 'movie' or data['type'] == 'show' or data['type'] == 'episode') and data['rating']:
% if data['rating']:
<div id="stars" class="rateit hidden-xs hidden-sm" data-rateit-value=""
data-rateit-ispreset="true" data-rateit-readonly="true"></div>
% endif
<div class="summary-content-director">
% if (data['type'] == 'episode' or data['type'] == 'movie') and data['directors']:
<div class="summary-content-details-tag">
% if data['directors']:
Directed by <strong> ${data['directors'][0]}</strong>
% endif
</div>
<div class="summary-content-studio">
% if (data['type'] == 'show' or data['type'] == 'movie') and data['studio']:
<div class="summary-content-details-tag">
% if data['studio']:
Studio <strong> ${data['studio']}</strong>
% endif
</div>
<div class="summary-content-airdate">
<div class="summary-content-details-tag">
% if data['type'] == 'movie':
Year <strong> ${data['year']}</strong>
% elif data['type'] == 'show':
Aired <strong> ${data['year']}</strong>
% elif data['type'] == 'episode':
Aired <strong> <span id="airdate">${data['originally_available_at']}</span></strong>
% elif data['type'] == 'album' or data['type'] == 'track':
Released <strong> ${data['year']}</strong>
% endif
</div>
<div class="summary-content-duration">
<div class="summary-content-details-tag">
% if data['duration']:
Runtime <strong> <span id="runtime">${data['duration']}</span> mins</strong>
% endif
</div>
<div class="summary-content-content-rating">
% if (data['type'] == 'episode' or data['type'] == 'movie' or data['type'] == 'show') and data['content_rating']:
<div class="summary-content-details-tag">
% if data['content_rating']:
Rated <strong> ${data['content_rating']} </strong>
% endif
</div>
</div>
% if data['type'] == 'movie' and data['tagline']:
% if data['tagline']:
<div class="summary-content-summary">
<p><strong> ${data['tagline']} </strong></p>
</div>
@@ -156,7 +207,7 @@ DOCUMENTATION :: END
</div>
<div class="col-md-3">
<div class="summary-content-people-wrapper hidden-xs hidden-sm">
% if (data['type'] == 'episode' or data['type'] == 'movie') and data['writers']:
% if data['writers']:
<div class="summary-content-writers">
<strong>Written by</strong>
<ul>
@@ -170,7 +221,7 @@ DOCUMENTATION :: END
</ul>
</div>
% endif
% if (data['type'] == 'movie' or data['type'] == 'show') and data['actors']:
% if data['actors']:
<div class="summary-content-actors">
<strong>Starring</strong>
<ul>
@@ -186,7 +237,7 @@ DOCUMENTATION :: END
% endif
</div>
<div class="summary-content-people-wrapper hidden-xs hidden-sm">
% if (data['type'] == 'movie' or data['type'] == 'show') and data['genres']:
% if data['genres']:
<div class="summary-content-genres">
<strong>Genres</strong>
<ul>
@@ -210,7 +261,7 @@ DOCUMENTATION :: END
</div>
</div>
<div class='table-card-back'>
<div id="season-list"></div>
<div id="children-list"></div>
</div>
</div>
% elif data['type'] == 'season':
@@ -221,11 +272,32 @@ DOCUMENTATION :: END
</div>
</div>
<div class='table-card-back'>
<div id="episode-list"></div>
<div id="children-list"></div>
</div>
</div>
% elif data['type'] == 'artist':
<div class='col-md-12'>
<div class='table-card-header'>
<div class="header-bar">
<span>Album List for <strong>${data['title']}</strong></span>
</div>
</div>
<div class='table-card-back'>
<div id="children-list"></div>
</div>
</div>
% elif data['type'] == 'album':
<div class='col-md-12'>
<div class='table-card-header'>
<div class="header-bar">
<span>Track List for <strong>${data['title']}</strong></span>
</div>
</div>
<div class='table-card-back'>
<div id="children-list"></div>
</div>
</div>
% endif
% if data['type'] == 'movie' or data['type'] == 'episode' or data['type'] == 'show' or data['type'] == 'season':
<div class='col-md-12'>
<div class='table-card-header'>
<div class="header-bar">
@@ -263,8 +335,25 @@ DOCUMENTATION :: END
</div>
<div class="modal fade" id="ip-info-modal" tabindex="-1" role="dialog" aria-labelledby="ip-info-modal">
</div>
<div class="modal fade" id="confirm-modal" tabindex="-1" role="dialog" aria-labelledby="confirm-modal">
<div class="modal-dialog">
<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" id="myModalLabel">Confirm Delete</h4>
</div>
<div class="modal-body" style="text-align: center;">
<p>Are you REALLY sure you want to delete <strong><span id="deleteCount"></span></strong> history item(s)?</p>
<p>This is permanent and cannot be undone!</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-dark" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-danger btn-ok" data-dismiss="modal" id="confirm-delete">Delete</button>
</div>
</div>
</div>
</div>
</div>
% endif
</div>
</div>
</div>
@@ -295,46 +384,14 @@ DOCUMENTATION :: END
% if data['type'] == 'movie' or data['type'] == 'show' or data['type'] == 'episode':
<script>
// Convert rating to 5 star rating type
var starRating = Math.round(${data['rating']} / 2)
$('#stars').attr('data-rateit-value', starRating)
var starRating = Math.round(${data['rating']} / 2);
$('#stars').attr('data-rateit-value', starRating);
</script>
% endif
% if data['type'] == 'movie' or data['type'] == 'episode':
<script src="interfaces/default/js/tables/history_table.js"></script>
% if data['type'] == 'show' or data['type'] == 'artist':
<script>
$(document).ready(function () {
history_table_options.ajax = {
"url": "get_history",
type: 'post',
data: function ( d ) {
return { 'json_data': JSON.stringify( d ),
'rating_key': ${data['rating_key']} };
}
}
history_table = $('#history_table').DataTable(history_table_options);
var colvis = new $.fn.dataTable.ColVis(history_table, { buttonText: '<i class="fa fa-columns"></i> Select columns', buttonClass: 'btn btn-dark', exclude: [0, 10] });
$(colvis.button()).appendTo('div.colvis-button-bar');
clearSearchButton('history_table', history_table);
$('#row-edit-mode').click(function() {
if ($(this).hasClass('active')) {
$('.delete-control').each(function() {
$(this).addClass('hidden');
});
} else {
$('.delete-control').each(function() {
$(this).removeClass('hidden');
});
}
});
});
</script>
% elif data['type'] == 'show':
<script src="interfaces/default/js/tables/history_table.js"></script>
<script>
$(document).ready(function () {
function get_history() {
history_table_options.ajax = {
"url": "get_history",
type: 'post',
@@ -343,63 +400,11 @@ DOCUMENTATION :: END
'grandparent_rating_key': ${data['rating_key']} };
}
}
history_table = $('#history_table').DataTable(history_table_options);
var colvis = new $.fn.dataTable.ColVis(history_table, { buttonText: '<i class="fa fa-columns"></i> Select columns', buttonClass: 'btn btn-dark', exclude: [0, 10] });
$(colvis.button()).appendTo('div.colvis-button-bar');
clearSearchButton('history_table', history_table);
$('#row-edit-mode').on('click', function() {
$('#row-edit-mode-alert').fadeIn(200);
if ($(this).hasClass('active')) {
if (history_to_delete.length > 0) {
$('#deleteCount').text(history_to_delete.length);
$('#confirm-modal').modal();
$('#confirm-modal').one('click', '#confirm-delete', function () {
for (var i = 0; i < history_to_delete.length; i++) {
$.ajax({
url: 'delete_history_rows',
data: { row_id: history_to_delete[i] },
async: true,
success: function (data) {
var msg = "History deleted";
showMsg(msg, false, true, 2000);
}
});
}
history_table.draw();
});
}
$('.delete-control').each(function () {
$(this).addClass('hidden');
$('#row-edit-mode-alert').fadeOut(200);
});
} else {
history_to_delete = [];
$('.delete-control').each(function() {
$(this).find('button.btn-danger').toggleClass('btn-warning').toggleClass('btn-danger');
$(this).removeClass('hidden');
});
}
});
});
$.ajax({
url: 'get_show_children',
type: "GET",
async: true,
data: { rating_key : ${data['rating_key']} },
complete: function(xhr, status) {
$("#season-list").html(xhr.responseText); }
});
}
</script>
% endif
% if data['type'] == 'season':
<script src="interfaces/default/js/tables/history_table.js"></script>
% elif data['type'] == 'season' or data['type'] == 'album':
<script>
$(document).ready(function () {
function get_history() {
history_table_options.ajax = {
"url": "get_history",
type: 'post',
@@ -408,6 +413,25 @@ DOCUMENTATION :: END
'parent_rating_key': ${data['rating_key']} };
}
}
}
</script>
% elif data['type'] == 'episode' or data['type'] == 'track' or data['type'] == 'movie':
<script>
function get_history() {
history_table_options.ajax = {
"url": "get_history",
type: 'post',
data: function ( d ) {
return { 'json_data': JSON.stringify( d ),
'rating_key': ${data['rating_key']} };
}
}
}
</script>
% endif
<script>
$(document).ready(function () {
get_history();
history_table = $('#history_table').DataTable(history_table_options);
var colvis = new $.fn.dataTable.ColVis(history_table, { buttonText: '<i class="fa fa-columns"></i> Select columns', buttonClass: 'btn btn-dark', exclude: [0, 10] });
$(colvis.button()).appendTo('div.colvis-button-bar');
@@ -451,23 +475,23 @@ DOCUMENTATION :: END
}
});
});
</script>
% if data['type'] == 'show' or data['type'] == 'season' or data['type'] == 'artist' or data['type'] == 'album':
<script>
$.ajax({
url: 'get_season_children',
url: 'get_item_children',
type: "GET",
async: true,
data: { rating_key : ${data['rating_key']} },
complete: function(xhr, status) {
$("#episode-list").html(xhr.responseText); }
$("#children-list").html(xhr.responseText); }
});
</script>
% endif
<script>
$("#airdate").html(moment($("#airdate").text()).format('MMM DD, YYYY'));
$("#runtime").html(millisecondsToMinutes($("#runtime").text(), true));
</script>
% endif
<script>
$('div.art-face').animate({ opacity: 0.2 }, { duration: 1000 });
</script>
% endif
</%def>

View File

@@ -0,0 +1,102 @@
<%doc>
USAGE DOCUMENTATION :: PLEASE LEAVE THIS AT THE TOP OF THIS FILE
For Mako templating syntax documentation please visit: http://docs.makotemplates.org/en/latest/
Filename: info_children_list.html
Version: 0.1
Variable names: data [list]
data :: Usable parameters
== Global keys ==
children_type Returns the type of children in the array.
children_count Returns the number of episodes in the array.
children_list Returns an array of episodes.
data['children_list'] :: Usable paramaters
== Global keys ==
rating_key Returns the unique identifier for the media item.
index Returns the episode number.
title Returns the name of the episode.
thumb Returns the location of the item's thumbnail. Use with pms_image_proxy.
parent_thumb Returns the location of the item's parent thumbnail. Use with pms_image_proxy.
DOCUMENTATION :: END
</%doc>
% if data != None:
% if data['children_count'] > 0:
<div class="item-children-wrapper">
<ul class="item-children-instance list-unstyled">
% for child in data['children_list']:
% if child['rating_key']:
% if data['children_type'] == 'track':
<li class="item-children-list-item">
% else:
<li>
% endif
<a href="info?item_id=${child['rating_key']}">
%if data['children_type'] == 'season':
<div class="item-children-poster">
% if child['thumb']:
<div class="item-children-poster-face season-poster" style="background-image: url(pms_image_proxy?img=${child['thumb']}&width=300&height=450);">
% else:
<div class="item-children-poster-face season-poster" style="background-image: url(pms_image_proxy?img=${child['parent_thumb']}&width=300&height=450);">
% endif
<div class="item-children-card-overlay">
<div class="item-children-overlay-text">
Season ${child['index']}
</div>
</div>
</div>
</div>
% elif data['children_type'] == 'episode':
<div class="item-children-poster">
<div class="item-children-poster-face episode-poster" style="background-image: url(pms_image_proxy?img=${child['thumb']}&width=300&height=450);">
<div class="item-children-card-overlay">
<div class="item-children-overlay-text">
Episode ${child['index']}
</div>
</div>
</div>
</div>
<div class="item-children-instance-text-wrapper episode-item">
<h3>${child['title']}</h3>
</div>
% elif data['children_type'] == 'album':
<div class="item-children-poster">
<div class="item-children-poster-face album-poster" style="background-image: url(pms_image_proxy?img=${child['thumb']}&width=300&height=300);"></div>
</div>
<div class="item-children-instance-text-wrapper album-item">
<h3>${child['title']}</h3>
</div>
% elif data['children_type'] == 'track':
% if loop.index % 2 == 0:
<div class="item-children-list-item-even">
<span class="item-children-list-item-index">${child['index']}</span>
<span class="item-children-list-item-title">${child['title']}</span>
<span class="item-children-list-item-duration" id="item-children-list-item-duration-${loop.index + 1}">
<script>$('#item-children-list-item-duration-${loop.index + 1}').text(moment.utc(${child['duration']}).format("m:ss"));</script>
</span>
</div>
% else:
<div class="item-children-list-item-odd">
<span class="item-children-list-item-index">${child['index']}</span>
<span class="item-children-list-item-title">${child['title']}</span>
<span class="item-children-list-item-duration" id="item-children-list-item-duration-${loop.index + 1}">
<script>$('#item-children-list-item-duration-${loop.index + 1}').text(moment.utc(${child['duration']}).format("m:ss"));</script>
</span>
</div>
% endif
% endif
</a>
</li>
% endif
% endfor
</ul>
</div>
% endif
% endif

View File

@@ -1,53 +0,0 @@
<%doc>
USAGE DOCUMENTATION :: PLEASE LEAVE THIS AT THE TOP OF THIS FILE
For Mako templating syntax documentation please visit: http://docs.makotemplates.org/en/latest/
Filename: info_episode_list.html
Version: 0.1
Variable names: data [list]
data :: Usable parameters
== Global keys ==
episode_count Returns the number of episodes in the array.
episode_list Returns an array of episodes.
data['episode_list'] :: Usable paramaters
== Global keys ==
rating_key Returns the unique identifier for the media item.
thumb Returns the location of the item's thumbnail. Use with pms_image_proxy.
title Returns the name of the episode.
index Returns the episode number.
DOCUMENTATION :: END
</%doc>
% if data != None:
% if data['episode_count'] > 0:
<div class="season-episodes-wrapper">
<ul class="season-episodes-instance list-unstyled">
% for a in data['episode_list']:
<li>
<a href="info?item_id=${a['rating_key']}">
<div class="season-episodes-poster">
<div class="season-episodes-poster-face" style="background-image: url(pms_image_proxy?img=${a['thumb']}&width=500&height=280);">
<div class="season-episodes-card-overlay">
<div class="season-episodes-overlay-text">
Episode ${a['index']}
</div>
</div>
</div>
</div>
<div class="season-episodes-instance-text-wrapper">
<h3>${a['title']}</h3>
</div>
</a>
</li>
% endfor
</ul>
</div>
% endif
% endif

View File

@@ -1,55 +0,0 @@
<%doc>
USAGE DOCUMENTATION :: PLEASE LEAVE THIS AT THE TOP OF THIS FILE
For Mako templating syntax documentation please visit: http://docs.makotemplates.org/en/latest/
Filename: info_season_list.html
Version: 0.1
Variable names: data [list]
data :: Usable parameters
== Global keys ==
season_count Returns the number of seasons in the array.
season_list Returns an array of seasons.
data['season_list'] :: Usable paramaters
== Global keys ==
rating_key Returns the unique identifier for the media item.
thumb Returns the location of the item's thumbnail. Use with pms_image_proxy.
title Returns the name of the season.
index Returns the season number.
DOCUMENTATION :: END
</%doc>
% if data != None:
% if data['season_count'] > 0:
<div class="show-seasons-wrapper">
<ul class="show-seasons-instance list-unstyled">
% for a in data['season_list']:
% if a['rating_key']:
<li>
<a href="info?item_id=${a['rating_key']}">
<div class="show-seasons-poster">
% if a['thumb']:
<div class="poster-face" style="background-image: url(pms_image_proxy?img=${a['thumb']}&width=300&height=450);">
% else:
<div class="poster-face" style="background-image: url(pms_image_proxy?img=${a['parent_thumb']}&width=300&height=450);">
% endif
<div class="show-seasons-card-overlay">
<div class="show-seasons-overlay-text">
Season ${a['index']}
</div>
</div>
</div>
</div>
</a>
</li>
% endif
% endfor
</ul>
</div>
% endif
% endif

View File

@@ -35,7 +35,7 @@ var hc_plays_by_day_options = {
}
}
},
colors: ['#F9AA03', '#FFFFFF'],
colors: ['#F9AA03', '#FFFFFF', '#FF4747'],
xAxis: {
type: 'datetime',
labels: {

View File

@@ -29,7 +29,7 @@ var hc_plays_by_dayofweek_options = {
credits: {
enabled: false
},
colors: ['#F9AA03', '#FFFFFF'],
colors: ['#F9AA03', '#FFFFFF', '#FF4747'],
xAxis: {
categories: [{}],
labels: {
@@ -46,8 +46,26 @@ var hc_plays_by_dayofweek_options = {
style: {
color: '#aaa'
}
},
stackLabels: {
enabled: false,
style: {
color: '#fff'
}
}
},
plotOptions: {
column: {
stacking: 'normal',
borderWidth: '0',
dataLabels: {
enabled: false,
style: {
color: '#000'
}
}
}
},
tooltip: {
shared: true
},

View File

@@ -29,7 +29,7 @@ var hc_plays_by_hourofday_options = {
credits: {
enabled: false
},
colors: ['#F9AA03', '#FFFFFF'],
colors: ['#F9AA03', '#FFFFFF', '#FF4747'],
xAxis: {
categories: [{}],
labels: {
@@ -46,8 +46,26 @@ var hc_plays_by_hourofday_options = {
style: {
color: '#aaa'
}
},
stackLabels: {
enabled: false,
style: {
color: '#fff'
}
}
},
plotOptions: {
column: {
stacking: 'normal',
borderWidth: '0',
dataLabels: {
enabled: false,
style: {
color: '#000'
}
}
}
},
tooltip: {
shared: true
},

View File

@@ -23,7 +23,7 @@ var hc_plays_by_month_options = {
credits: {
enabled: false
},
colors: ['#F9AA03', '#FFFFFF'],
colors: ['#F9AA03', '#FFFFFF', '#FF4747'],
xAxis: {
labels: {
style: {

View File

@@ -29,7 +29,7 @@ var hc_plays_by_platform_options = {
credits: {
enabled: false
},
colors: ['#F9AA03', '#FFFFFF'],
colors: ['#F9AA03', '#FFFFFF', '#FF4747'],
xAxis: {
categories: [{}],
labels: {
@@ -46,8 +46,26 @@ var hc_plays_by_platform_options = {
style: {
color: '#aaa'
}
},
stackLabels: {
enabled: false,
style: {
color: '#fff'
}
}
},
plotOptions: {
column: {
stacking: 'normal',
borderWidth: '0',
dataLabels: {
enabled: false,
style: {
color: '#000'
}
}
}
},
tooltip: {
shared: true
},

View File

@@ -29,7 +29,7 @@ var hc_plays_by_source_resolution_options = {
credits: {
enabled: false
},
colors: ['#F9AA03', '#FFFFFF'],
colors: ['#F9AA03', '#FFFFFF', '#FF4747'],
xAxis: {
categories: [{}],
labels: {
@@ -46,8 +46,26 @@ var hc_plays_by_source_resolution_options = {
style: {
color: '#aaa'
}
},
stackLabels: {
enabled: false,
style: {
color: '#fff'
}
}
},
plotOptions: {
column: {
stacking: 'normal',
borderWidth: '0',
dataLabels: {
enabled: false,
style: {
color: '#000'
}
}
}
},
tooltip: {
shared: true
},

View File

@@ -29,7 +29,7 @@ var hc_plays_by_stream_resolution_options = {
credits: {
enabled: false
},
colors: ['#F9AA03', '#FFFFFF'],
colors: ['#F9AA03', '#FFFFFF', '#FF4747'],
xAxis: {
categories: [{}],
labels: {
@@ -46,8 +46,26 @@ var hc_plays_by_stream_resolution_options = {
style: {
color: '#aaa'
}
},
stackLabels: {
enabled: false,
style: {
color: '#fff'
}
}
},
plotOptions: {
column: {
stacking: 'normal',
borderWidth: '0',
dataLabels: {
enabled: false,
style: {
color: '#000'
}
}
}
},
tooltip: {
shared: true
},

View File

@@ -29,7 +29,7 @@ var hc_plays_by_user_options = {
credits: {
enabled: false
},
colors: ['#F9AA03', '#FFFFFF'],
colors: ['#F9AA03', '#FFFFFF', '#FF4747'],
xAxis: {
categories: [{}],
labels: {
@@ -46,8 +46,26 @@ var hc_plays_by_user_options = {
style: {
color: '#aaa'
}
},
stackLabels: {
enabled: false,
style: {
color: '#fff'
}
}
},
plotOptions: {
column: {
stacking: 'normal',
borderWidth: '0',
dataLabels: {
enabled: false,
style: {
color: '#000'
}
}
}
},
tooltip: {
shared: true
},

View File

@@ -219,7 +219,11 @@ function getPlatformImagePath(platformName) {
return 'interfaces/default/images/platforms/playstation.png';
} else if (platformName.indexOf("Mystery 5") > -1) {
return 'interfaces/default/images/platforms/xbox.png';
} else {
} else if (platformName.indexOf("Windows") > -1) {
return 'interfaces/default/images/platforms/win8.png';
} else if (platformName.indexOf("Windows phone") > -1) {
return 'interfaces/default/images/platforms/wp.png';
} else {
return 'interfaces/default/images/platforms/default.png';
}
}

View File

@@ -125,12 +125,12 @@ history_table_options = {
} else if (rowData['media_type'] === 'episode') {
media_type = '<span class="media-type-tooltip" data-toggle="tooltip" title="Episode"><i class="fa fa-television fa-fw"></i></span>';
thumb_popover = '<span class="thumb-tooltip" data-toggle="popover" data-img="pms_image_proxy?img=' + rowData['thumb'] + '&width=300&height=450&fallback=poster" data-height="120">' + cellData + ' \
(S' + ('00' + rowData['parent_media_index']).slice(-2) + 'E' + ('00' + rowData['media_index']).slice(-2) + ')</span>'
(S' + rowData['parent_media_index'] + '&middot; E' + rowData['media_index'] + ')</span>'
$(td).html('<div class="history-title"><a href="info?source=history&item_id=' + rowData['id'] + '"><div style="float: left;" >' + media_type + '&nbsp' + thumb_popover + '</div></a></div>');
} else if (rowData['media_type'] === 'track') {
media_type = '<span class="media-type-tooltip" data-toggle="tooltip" title="Track"><i class="fa fa-music fa-fw"></i></span>';
thumb_popover = '<span class="thumb-tooltip" data-toggle="popover" data-img="pms_image_proxy?img=' + rowData['thumb'] + '&width=300&height=300&fallback=poster" data-height="80">' + cellData + ' (' + rowData['parent_title'] + ')</span>'
$(td).html('<div class="history-title"><div style="float: left;">' + media_type + '&nbsp' + thumb_popover + '</div></div>');
$(td).html('<div class="history-title"><a href="info?source=history&item_id=' + rowData['id'] + '"><div style="float: left;">' + media_type + '&nbsp' + thumb_popover + '</div></a></div>');
} else {
$(td).html('<a href="info?item_id=' + rowData['id'] + '">' + cellData + '</a>');
}

View File

@@ -103,12 +103,12 @@ history_table_modal_options = {
} else if (rowData['media_type'] === 'episode') {
media_type = '<span class="media-type-tooltip" data-toggle="tooltip" title="Episode"><i class="fa fa-television fa-fw"></i></span>';
thumb_popover = '<span class="thumb-tooltip" data-toggle="popover" data-img="pms_image_proxy?img=' + rowData['thumb'] + '&width=300&height=450&fallback=poster" data-height="120">' + cellData + ' \
(S' + ('00' + rowData['parent_media_index']).slice(-2) + 'E' + ('00' + rowData['media_index']).slice(-2) + ')</span>'
(S' + rowData['parent_media_index'] + '&middot; E' + rowData['media_index'] + ')</span>'
$(td).html('<div class="history-title"><a href="info?source=history&item_id=' + rowData['id'] + '"><div style="float: left;" >' + media_type + '&nbsp' + thumb_popover + '</div></a></div>');
} else if (rowData['media_type'] === 'track') {
media_type = '<span class="media-type-tooltip" data-toggle="tooltip" title="Track"><i class="fa fa-music fa-fw"></i></span>';
thumb_popover = '<span class="thumb-tooltip" data-toggle="popover" data-img="pms_image_proxy?img=' + rowData['thumb'] + '&width=300&height=300&fallback=poster" data-height="80">' + cellData + ' (' + rowData['parent_title'] + ')</span>'
$(td).html('<div class="history-title"><div style="float: left;">' + media_type + '&nbsp' + thumb_popover + '</div></div>');
$(td).html('<div class="history-title"><a href="info?source=history&item_id=' + rowData['id'] + '"><div style="float: left;">' + media_type + '&nbsp' + thumb_popover + '</div></a></div>');
} else {
$(td).html('<a href="info?item_id=' + rowData['id'] + '">' + cellData + '</a>');
}

View File

@@ -49,7 +49,7 @@ sync_table_options = {
"data": "title",
"createdCell": function (td, cellData, rowData, row, col) {
if (cellData !== '') {
if (rowData['metadata_type'] !== 'track') {
if (rowData['metadata_type'] !== '') {
$(td).html('<a href="info?item_id=' + rowData['rating_key'] + '">' + cellData + '</a>');
} else {
$(td).html(cellData);

View File

@@ -86,7 +86,7 @@ user_ip_table_options = {
} else if (rowData['media_type'] === 'track') {
media_type = '<span class="media-type-tooltip" data-toggle="tooltip" title="Track"><i class="fa fa-music fa-fw"></i></span>';
thumb_popover = '<span class="thumb-tooltip" data-toggle="popover" data-img="pms_image_proxy?img=' + rowData['thumb'] + '&width=80&height=80&fallback=poster" data-height="80">' + cellData + '</span>'
$(td).html('<div class="history-title"><div style="float: left;">' + media_type + '&nbsp' + thumb_popover + '</div></div>');
$(td).html('<div class="history-title"><a href="info?source=history&item_id=' + rowData['id'] + '"><div style="float: left;">' + media_type + '&nbsp' + thumb_popover + '</div></a></div>');
} else if (rowData['media_type']) {
$(td).html('<a href="info?item_id=' + rowData['id'] + '">' + cellData + '</a>');
} else {

View File

@@ -141,7 +141,7 @@ users_list_table_options = {
} else if (rowData['media_type'] === 'track') {
media_type = '<span class="media-type-tooltip" data-toggle="tooltip" title="Track"><i class="fa fa-music fa-fw"></i></span>';
thumb_popover = '<span class="thumb-tooltip" data-toggle="popover" data-img="pms_image_proxy?img=' + rowData['thumb'] + '&width=80&height=80&fallback=poster" data-height="80">' + cellData + '</span>'
$(td).html('<div class="history-title"><div style="float: left;">' + media_type + '&nbsp' + thumb_popover + '</div></div>');
$(td).html('<div class="history-title"><a href="info?source=history&item_id=' + rowData['id'] + '"><div style="float: left;">' + media_type + '&nbsp' + thumb_popover + '</div></a></div>');
} else if (rowData['media_type']) {
$(td).html('<a href="info?item_id=' + rowData['id'] + '">' + cellData + '</a>');
} else {

View File

@@ -31,35 +31,48 @@ DOCUMENTATION :: END
<li>
% if item['type'] == 'season' or item['type'] == 'movie':
<a href="info?item_id=${item['rating_key']}">
<div class="poster">
<div class="poster-face" style="background-image: url(pms_image_proxy?img=${item['thumb']}&width=300&height=450&fallback=poster);"></div>
<div class="dashboard-recent-media-poster">
<div class="dashboard-recent-media-poster-face" style="background-image: url(pms_image_proxy?img=${item['thumb']}&width=300&height=450&fallback=poster);">
<div class="dashboard-recent-media-overlay">
<div class="dashboard-recent-media-overlay-text" id="added_at-${item['rating_key']}">
<script>
$('#added_at-${item['rating_key']}').text('Added ' + moment(${item['added_at']}, "X").fromNow())
</script>
</div>
</div>
</div>
</div>
<div class="dashboard-recent-media-metacontainer">
% if item['type'] == 'season':
<h3>${item['parent_title']}</h3>
<h3>(${item['title']})</h3>
<h3 class="text-muted">${item['title']}</h3>
% elif item['type'] == 'movie':
<h3>${item['title']}</h3>
<h3>(${item['year']})</h3>
<h3 class="text-muted">${item['year']}</h3>
% endif
<div class="text-muted" id="added_at-${item['rating_key']}">${item['added_at']}</div>
</div>
</a>
% elif item['type'] == 'album':
<div class="poster">
<div class="cover-face" style="background-image: url(pms_image_proxy?img=${item['thumb']}&width=300&height=300&fallback=cover);"></div>
</div>
<div class="dashboard-recent-media-metacontainer">
<h3>${item['parent_title']}</h3>
<h3>${item['title']}</h3>
<div class="text-muted" id="added_at-${item['rating_key']}">${item['added_at']}</div>
</div>
<a href="info?item_id=${item['rating_key']}">
<div class="dashboard-recent-media-cover">
<div class="dashboard-recent-media-cover-face" style="background-image: url(pms_image_proxy?img=${item['thumb']}&width=300&height=300&fallback=cover);">
<div class="dashboard-recent-media-overlay">
<div class="dashboard-recent-media-overlay-text" id="added_at-${item['rating_key']}">
<script>
$('#added_at-${item['rating_key']}').text('Added ' + moment(${item['added_at']}, "X").fromNow())
</script>
</div>
</div>
</div>
</div>
<div class="dashboard-recent-media-metacontainer">
<h3>${item['parent_title']}</h3>
<h3 class="text-muted">${item['title']}</h3>
</div>
</a>
% endif
</li>
</div>
<script>
$('#added_at-${item['rating_key']}').html('Added ' + moment(${item['added_at']}, "X").fromNow())
</script>
% endfor
</ul>
</div>

View File

@@ -282,12 +282,13 @@ available_notification_agents = notifiers.available_notification_agents()
<div class="row">
<div class="col-md-6">
<div class="input-group">
<input type="text" class="form-control" id="pms_token" name="pms_token" value="${config['pms_token']}" data-parsley-trigger="change" required>
<input type="text" class="form-control" id="pms_token" name="pms_token" value="${config['pms_token']}" data-parsley-trigger="change" data-parsley-errors-container="#pms_token_error" required>
<span class="input-group-btn">
<button class="btn btn-form" type="button" data-toggle="modal" data-target="#pms-auth-modal">Fetch Token</button>
</span>
</div>
</div>
<div id="pms_token_error" class="alert alert-danger settings-alert" role="alert"></div>
</div>
<p class="help-block">Token for Plex.tv authentication.</p>
</div>
@@ -1168,7 +1169,7 @@ $(document).ready(function() {
function checkLogsPath() {
if ($("#pms_logs_folder").val() == '') {
$("#debugLogCheck").html("You must first define your Plex Server Logs folder path under the Extra Settings tab.");
$("#debugLogCheck").html("You must first define your Plex Server Logs folder path under the Plex Media Server tab.");
$("#ip_logging_enable").attr("disabled", true);
} else {
$("#ip_logging_enable").attr("disabled", false);

View File

@@ -32,29 +32,54 @@ DOCUMENTATION :: END
<div class="dashboard-recent-media-row">
<ul class="dashboard-recent-media list-unstyled">
% for item in data:
<div class="dashboard-recent-media-instance">
<li>
<a href="info?source=history&item_id=${item['row_id']}">
<div class="poster">
<div class="poster-face" style="background-image: url(pms_image_proxy?img=${item['thumb']}&width=300&height=450&fallback=poster);"></div>
<li>
% if item['type'] == 'episode' or item['type'] == 'movie':
<a href="info?source=history&item_id=${item['row_id']}">
<div class="dashboard-recent-media-poster">
<div class="dashboard-recent-media-poster-face" style="background-image: url(pms_image_proxy?img=${item['thumb']}&width=300&height=450&fallback=poster);">
<div class="dashboard-recent-media-overlay">
<div class="dashboard-recent-media-overlay-text" id="time-${item['time']}">
<script>
$('#time-${item['time']}').text('Watched ' + moment(${item['time']}, "X").fromNow())
</script>
</div>
</div>
</div>
<div class="dashboard-recent-media-metacontainer">
% if item['type'] == 'episode':
<h3>${item['parent_title']}</h3>
<h3>${item['title']}</h3>
<h3>(Season ${item['parent_index']}, Episode ${item['index']})</h3>
% elif item['type'] == 'movie':
<h3>${item['title']}</h3>
<h3>(${item['year']})</h3>
% endif
<div class="text-muted" id="time-${item['time']}">${item['time']}</div>
</div>
</a>
</li>
</div>
<script>
$('#time-${item['time']}').html('Watched ' + moment(${item['time']}, "X").fromNow())
</script>
</div>
<div class="dashboard-recent-media-metacontainer">
% if item['type'] == 'episode':
<h3>${item['grandparent_title']}</h3>
<h3>${item['title']}</h3>
<h3 class="text-muted">S${item['parent_index']} &middot; E${item['index']}</h3>
% elif item['type'] == 'movie':
<h3>${item['title']}</h3>
<h3 class="text-muted">${item['year']}</h3>
% endif
<div class="text-muted" id="time-${item['time']}">
</div>
</div>
</a>
% elif item['type'] == 'track':
<a href="info?source=history&item_id=${item['row_id']}">
<div class="dashboard-recent-media-cover">
<div class="dashboard-recent-media-cover-face" style="background-image: url(pms_image_proxy?img=${item['thumb']}&width=300&height=300&fallback=cover);">
<div class="dashboard-recent-media-overlay">
<div class="dashboard-recent-media-overlay-text" id="time-${item['time']}">
<script>
$('#time-${item['time']}').text('Watched ' + moment(${item['time']}, "X").fromNow())
</script>
</div>
</div>
</div>
</div>
<div class="dashboard-recent-media-metacontainer">
<h3>${item['grandparent_title']}</h3>
<h3>${item['title']}</h3>
<h3 class="text-muted">${item['parent_title']}</h3>
</div>
</a>
% endif
</li>
% endfor
</ul>
</div>

View File

@@ -153,10 +153,10 @@ class DataFactory(object):
query = 'SELECT session_history_metadata.id, ' \
'session_history_metadata.grandparent_title, ' \
'COUNT(session_history_metadata.grandparent_title) as total_plays, ' \
'cast(round(SUM(round((julianday(datetime(session_history.stopped, "unixepoch", "localtime")) - ' \
'julianday(datetime(session_history.started, "unixepoch", "localtime"))) * 86400) - ' \
'(CASE WHEN session_history.paused_counter IS NULL THEN 0 ' \
'ELSE session_history.paused_counter END))/60) as integer) as total_duration,' \
'SUM(case when session_history.stopped > 0 ' \
'then (session_history.stopped - session_history.started) ' \
' - (case when session_history.paused_counter is NULL then 0 else session_history.paused_counter end) ' \
'else 0 end) as total_duration, ' \
'session_history_metadata.grandparent_rating_key, ' \
'MAX(session_history.started) as last_watch,' \
'session_history_metadata.grandparent_thumb ' \
@@ -193,52 +193,6 @@ class DataFactory(object):
'stat_type': sort_type,
'rows': top_tv})
elif 'top_movies' in stat:
top_movies = []
try:
query = 'SELECT session_history_metadata.id, ' \
'session_history_metadata.full_title, ' \
'COUNT(session_history_metadata.full_title) as total_plays, ' \
'cast(round(SUM(round((julianday(datetime(session_history.stopped, "unixepoch", "localtime")) - ' \
'julianday(datetime(session_history.started, "unixepoch", "localtime"))) * 86400) - ' \
'(CASE WHEN session_history.paused_counter IS NULL THEN 0 ' \
'ELSE session_history.paused_counter END))/60) as integer) as total_duration,' \
'session_history_metadata.rating_key, ' \
'MAX(session_history.started) as last_watch,' \
'session_history_metadata.thumb ' \
'FROM session_history_metadata ' \
'JOIN session_history on session_history_metadata.id = session_history.id ' \
'WHERE datetime(session_history.stopped, "unixepoch", "localtime") ' \
'>= datetime("now", "-%s days", "localtime") ' \
'AND session_history_metadata.media_type = "movie" ' \
'GROUP BY session_history_metadata.full_title ' \
'ORDER BY %s DESC LIMIT %s' % (time_range, sort_type, stat_count)
result = monitor_db.select(query)
except:
logger.warn("Unable to execute database query.")
return None
for item in result:
row = {'title': item[1],
'total_plays': item[2],
'total_duration': item[3],
'users_watched': '',
'rating_key': item[4],
'last_play': item[5],
'grandparent_thumb': '',
'thumb': item[6],
'user': '',
'friendly_name': '',
'platform_type': '',
'platform': '',
'row_id': item[0]
}
top_movies.append(row)
home_stats.append({'stat_id': stat,
'stat_type': sort_type,
'rows': top_movies})
elif 'popular_tv' in stat:
popular_tv = []
try:
@@ -281,6 +235,52 @@ class DataFactory(object):
home_stats.append({'stat_id': stat,
'rows': popular_tv})
elif 'top_movies' in stat:
top_movies = []
try:
query = 'SELECT session_history_metadata.id, ' \
'session_history_metadata.full_title, ' \
'COUNT(session_history_metadata.full_title) as total_plays, ' \
'SUM(case when session_history.stopped > 0 ' \
'then (session_history.stopped - session_history.started) ' \
' - (case when session_history.paused_counter is NULL then 0 else session_history.paused_counter end) ' \
'else 0 end) as total_duration, ' \
'session_history_metadata.rating_key, ' \
'MAX(session_history.started) as last_watch,' \
'session_history_metadata.thumb ' \
'FROM session_history_metadata ' \
'JOIN session_history on session_history_metadata.id = session_history.id ' \
'WHERE datetime(session_history.stopped, "unixepoch", "localtime") ' \
'>= datetime("now", "-%s days", "localtime") ' \
'AND session_history_metadata.media_type = "movie" ' \
'GROUP BY session_history_metadata.full_title ' \
'ORDER BY %s DESC LIMIT %s' % (time_range, sort_type, stat_count)
result = monitor_db.select(query)
except:
logger.warn("Unable to execute database query.")
return None
for item in result:
row = {'title': item[1],
'total_plays': item[2],
'total_duration': item[3],
'users_watched': '',
'rating_key': item[4],
'last_play': item[5],
'grandparent_thumb': '',
'thumb': item[6],
'user': '',
'friendly_name': '',
'platform_type': '',
'platform': '',
'row_id': item[0]
}
top_movies.append(row)
home_stats.append({'stat_id': stat,
'stat_type': sort_type,
'rows': top_movies})
elif 'popular_movies' in stat:
popular_movies = []
try:
@@ -330,10 +330,10 @@ class DataFactory(object):
'(case when users.friendly_name is null then session_history.user else ' \
'users.friendly_name end) as friendly_name,' \
'COUNT(session_history.id) as total_plays, ' \
'cast(round(SUM(round((julianday(datetime(session_history.stopped, "unixepoch", "localtime")) - ' \
'julianday(datetime(session_history.started, "unixepoch", "localtime"))) * 86400) - ' \
'(CASE WHEN session_history.paused_counter IS NULL THEN 0 ' \
'ELSE session_history.paused_counter END))/60) as integer) as total_duration,' \
'SUM(case when session_history.stopped > 0 ' \
'then (session_history.stopped - session_history.started) ' \
' - (case when session_history.paused_counter is NULL then 0 else session_history.paused_counter end) ' \
'else 0 end) as total_duration, ' \
'MAX(session_history.started) as last_watch, ' \
'users.custom_avatar_url as thumb, ' \
'users.user_id ' \
@@ -382,10 +382,10 @@ class DataFactory(object):
try:
query = 'SELECT session_history.platform, ' \
'COUNT(session_history.id) as total_plays, ' \
'cast(round(SUM(round((julianday(datetime(session_history.stopped, "unixepoch", "localtime")) - ' \
'julianday(datetime(session_history.started, "unixepoch", "localtime"))) * 86400) - ' \
'(CASE WHEN session_history.paused_counter IS NULL THEN 0 ' \
'ELSE session_history.paused_counter END))/60) as integer) as total_duration,' \
'SUM(case when session_history.stopped > 0 ' \
'then (session_history.stopped - session_history.started) ' \
' - (case when session_history.paused_counter is NULL then 0 else session_history.paused_counter end) ' \
'else 0 end) as total_duration, ' \
'MAX(session_history.started) as last_watch ' \
'FROM session_history ' \
'WHERE datetime(session_history.stopped, "unixepoch", "localtime") ' \
@@ -524,24 +524,35 @@ class DataFactory(object):
try:
if user_id:
query = 'SELECT session_history.id, session_history.media_type, session_history.rating_key, title, ' \
'grandparent_title, thumb, parent_thumb, grandparent_thumb, media_index, parent_media_index, year, started, user ' \
query = 'SELECT session_history.id, session_history.media_type, session_history.rating_key, session_history.parent_rating_key, ' \
'title, parent_title, grandparent_title, thumb, parent_thumb, grandparent_thumb, media_index, parent_media_index, ' \
'year, started, user ' \
'FROM session_history_metadata ' \
'JOIN session_history ON session_history_metadata.id = session_history.id ' \
'WHERE user_id = ? AND session_history.media_type != "track" ORDER BY started DESC LIMIT ?'
'WHERE user_id = ? ' \
'GROUP BY (CASE WHEN session_history.media_type = "track" THEN session_history.parent_rating_key ' \
' ELSE session_history.rating_key END) ' \
'ORDER BY started DESC LIMIT ?'
result = monitor_db.select(query, args=[user_id, limit])
elif user:
query = 'SELECT session_history.id, session_history.media_type, session_history.rating_key, title, ' \
'grandparent_title, thumb, parent_thumb, grandparent_thumb, media_index, parent_media_index, year, started, user ' \
query = 'SELECT session_history.id, session_history.media_type, session_history.rating_key, session_history.parent_rating_key, ' \
'title, parent_title, grandparent_title, thumb, parent_thumb, grandparent_thumb, media_index, parent_media_index, ' \
'year, started, user ' \
'FROM session_history_metadata ' \
'JOIN session_history ON session_history_metadata.id = session_history.id ' \
'WHERE user = ? AND session_history.media_type != "track" ORDER BY started DESC LIMIT ?'
'WHERE user = ? ' \
'GROUP BY (CASE WHEN session_history.media_type = "track" THEN session_history.parent_rating_key ' \
' ELSE session_history.rating_key END) ' \
'ORDER BY started DESC LIMIT ?'
result = monitor_db.select(query, args=[user, limit])
else:
query = 'SELECT session_history.id, session_history.media_type, session_history.rating_key, title, ' \
'grandparent_title, thumb, parent_thumb, grandparent_thumb, media_index, parent_media_index, year, started, user ' \
'FROM session_history_metadata WHERE session_history.media_type != "track"' \
query = 'SELECT session_history.id, session_history.media_type, session_history.rating_key, session_history.parent_rating_key, ' \
'title, parent_title, grandparent_title, thumb, parent_thumb, grandparent_thumb, media_index, parent_media_index, ' \
'year, started, user ' \
'FROM session_history_metadata ' \
'JOIN session_history ON session_history_metadata.id = session_history.id ' \
'GROUP BY (CASE WHEN session_history.media_type = "track" THEN session_history.parent_rating_key ' \
' ELSE session_history.rating_key END) ' \
'ORDER BY started DESC LIMIT ?'
result = monitor_db.select(query, args=[limit])
except:
@@ -549,24 +560,25 @@ class DataFactory(object):
return None
for row in result:
if row[1] == 'episode' and row[6]:
thumb = row[6]
if row[1] == 'episode' and row[8]:
thumb = row[8]
elif row[1] == 'episode':
thumb = row[7]
thumb = row[9]
else:
thumb = row[5]
thumb = row[7]
recent_output = {'row_id': row[0],
'type': row[1],
'rating_key': row[2],
'title': row[3],
'parent_title': row[4],
'title': row[4],
'parent_title': row[5],
'grandparent_title': row[6],
'thumb': thumb,
'index': row[8],
'parent_index': row[9],
'year': row[10],
'time': row[11],
'user': row[12]
'index': row[10],
'parent_index': row[11],
'year': row[12],
'time': row[13],
'user': row[14]
}
recently_watched.append(recent_output)

View File

@@ -1,4 +1,4 @@
# This file is part of PlexPy.
# This file is part of PlexPy.
#
# PlexPy is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -33,7 +33,8 @@ class Graphs(object):
if y_axis == 'plays':
query = 'SELECT date(started, "unixepoch", "localtime") as date_played, ' \
'SUM(case when media_type = "episode" then 1 else 0 end) as tv_count, ' \
'SUM(case when media_type = "movie" then 1 else 0 end) as movie_count ' \
'SUM(case when media_type = "movie" then 1 else 0 end) as movie_count, ' \
'SUM(case when media_type = "track" then 1 else 0 end) as music_count ' \
'FROM session_history ' \
'WHERE datetime(stopped, "unixepoch", "localtime") >= datetime("now", "-%s days", "localtime") ' \
'GROUP BY date_played ' \
@@ -42,8 +43,12 @@ class Graphs(object):
result = monitor_db.select(query)
else:
query = 'SELECT date(started, "unixepoch", "localtime") as date_played, ' \
'SUM(case when media_type = "episode" and stopped > 0 then (stopped - started) else 0 end) as tv_duration, ' \
'SUM(case when media_type = "movie" and stopped > 0 then (stopped - started) else 0 end) as movie_duration ' \
'SUM(case when media_type = "episode" and stopped > 0 then (stopped - started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as tv_duration, ' \
'SUM(case when media_type = "movie" and stopped > 0 then (stopped - started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as movie_duration, ' \
'SUM(case when media_type = "track" and stopped > 0 then (stopped - started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as music_duration ' \
'FROM session_history ' \
'WHERE datetime(stopped, "unixepoch", "localtime") >= datetime("now", "-%s days", "localtime") ' \
'GROUP BY date_played ' \
@@ -62,31 +67,38 @@ class Graphs(object):
categories = []
series_1 = []
series_2 = []
series_3 = []
for date_item in sorted(date_list):
date_string = date_item.strftime('%Y-%m-%d')
categories.append(date_string)
series_1_value = 0
series_2_value = 0
series_3_value = 0
for item in result:
if date_string == item[0]:
series_1_value = item[1]
series_2_value = item[2]
series_3_value = item[3]
break
else:
series_1_value = 0
series_2_value = 0
series_3_value = 0
series_1.append(series_1_value)
series_2.append(series_2_value)
series_3.append(series_3_value)
series_1_output = {'name': 'TV',
'data': series_1}
series_2_output = {'name': 'Movies',
'data': series_2}
series_3_output = {'name': 'Music',
'data': series_3}
output = {'categories': categories,
'series': [series_1_output, series_2_output]}
'series': [series_1_output, series_2_output, series_3_output]}
return output
def get_total_plays_per_dayofweek(self, time_range='30', y_axis='plays'):
@@ -105,16 +117,16 @@ class Graphs(object):
'when 4 then "Thursday" ' \
'when 5 then "Friday" ' \
'else "Saturday" end as dayofweek, ' \
'COUNT(id) as total_plays ' \
'from session_history ' \
'SUM(case when media_type = "episode" then 1 else 0 end) as tv_count, ' \
'SUM(case when media_type = "movie" then 1 else 0 end) as movie_count, ' \
'SUM(case when media_type = "track" then 1 else 0 end) as music_count ' \
'FROM session_history ' \
'WHERE datetime(stopped, "unixepoch", "localtime") >= ' \
'datetime("now", "-' + time_range + ' days", "localtime") AND ' \
'(media_type = "episode" OR media_type = "movie") ' \
'datetime("now", "-' + time_range + ' days", "localtime") ' \
'GROUP BY dayofweek ' \
'ORDER BY daynumber'
result = monitor_db.select(query)
y_axis_label = 'Total plays'
else:
query = 'SELECT strftime("%w", datetime(started, "unixepoch", "localtime")) as daynumber, ' \
'case cast (strftime("%w", datetime(started, "unixepoch", "localtime")) as integer) ' \
@@ -125,40 +137,57 @@ class Graphs(object):
'when 4 then "Thursday" ' \
'when 5 then "Friday" ' \
'else "Saturday" end as dayofweek, ' \
'SUM(case when media_type != "track" and stopped > 0 then (stopped - started) else 0 end) as duration ' \
'from session_history ' \
'SUM(case when media_type = "episode" and stopped > 0 then (stopped - started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as tv_duration, ' \
'SUM(case when media_type = "movie" and stopped > 0 then (stopped - started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as movie_duration, ' \
'SUM(case when media_type = "track" and stopped > 0 then (stopped - started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as music_duration ' \
'FROM session_history ' \
'WHERE datetime(stopped, "unixepoch", "localtime") >= ' \
'datetime("now", "-' + time_range + ' days", "localtime") AND ' \
'(media_type = "episode" OR media_type = "movie") ' \
'datetime("now", "-' + time_range + ' days", "localtime") ' \
'GROUP BY dayofweek ' \
'ORDER BY daynumber'
result = monitor_db.select(query)
y_axis_label = 'Total duration'
days_list = ['Sunday', 'Monday', 'Tuesday', 'Wednesday',
'Thursday', 'Friday', 'Saturday']
categories = []
series_1 = []
series_2 = []
series_3 = []
for day_item in days_list:
categories.append(day_item)
series_1_value = 0
series_2_value = 0
series_3_value = 0
for item in result:
if day_item == item[1]:
series_1_value = item[2]
series_2_value = item[3]
series_3_value = item[4]
break
else:
series_1_value = 0
series_2_value = 0
series_3_value = 0
series_1.append(series_1_value)
series_2.append(series_2_value)
series_3.append(series_3_value)
series_1_output = {'name': y_axis_label,
series_1_output = {'name': 'TV',
'data': series_1}
series_2_output = {'name': 'Movies',
'data': series_2}
series_3_output = {'name': 'Music',
'data': series_3}
output = {'categories': categories,
'series': [series_1_output]}
'series': [series_1_output, series_2_output, series_3_output]}
return output
def get_total_plays_per_hourofday(self, time_range='30', y_axis='plays'):
@@ -169,28 +198,31 @@ class Graphs(object):
if y_axis == 'plays':
query = 'select strftime("%H", datetime(started, "unixepoch", "localtime")) as hourofday, ' \
'COUNT(id) ' \
'SUM(case when media_type = "episode" then 1 else 0 end) as tv_count, ' \
'SUM(case when media_type = "movie" then 1 else 0 end) as movie_count, ' \
'SUM(case when media_type = "track" then 1 else 0 end) as music_count ' \
'FROM session_history ' \
'WHERE datetime(stopped, "unixepoch", "localtime") >= ' \
'datetime("now", "-' + time_range + ' days", "localtime") AND ' \
'(media_type = "episode" OR media_type = "movie") ' \
'datetime("now", "-' + time_range + ' days", "localtime") ' \
'GROUP BY hourofday ' \
'ORDER BY hourofday'
result = monitor_db.select(query)
y_axis_label = 'Total plays'
else:
query = 'select strftime("%H", datetime(started, "unixepoch", "localtime")) as hourofday, ' \
'SUM(case when media_type != "track" and stopped > 0 then (stopped - started) else 0 end) as duration ' \
'SUM(case when media_type = "episode" and stopped > 0 then (stopped - started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as tv_duration, ' \
'SUM(case when media_type = "movie" and stopped > 0 then (stopped - started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as movie_duration, ' \
'SUM(case when media_type = "track" and stopped > 0 then (stopped - started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as music_duration ' \
'FROM session_history ' \
'WHERE datetime(stopped, "unixepoch", "localtime") >= ' \
'datetime("now", "-' + time_range + ' days", "localtime") AND ' \
'(media_type = "episode" OR media_type = "movie") ' \
'datetime("now", "-' + time_range + ' days", "localtime") ' \
'GROUP BY hourofday ' \
'ORDER BY hourofday'
result = monitor_db.select(query)
y_axis_label = 'Total duration'
hours_list = ['00','01','02','03','04','05',
'06','07','08','09','10','11',
@@ -199,24 +231,38 @@ class Graphs(object):
categories = []
series_1 = []
series_2 = []
series_3 = []
for hour_item in hours_list:
categories.append(hour_item)
series_1_value = 0
series_2_value = 0
series_3_value = 0
for item in result:
if hour_item == item[0]:
series_1_value = item[1]
series_2_value = item[2]
series_3_value = item[3]
break
else:
series_1_value = 0
series_2_value = 0
series_3_value = 0
series_1.append(series_1_value)
series_2.append(series_2_value)
series_3.append(series_3_value)
series_1_output = {'name': y_axis_label,
series_1_output = {'name': 'TV',
'data': series_1}
series_2_output = {'name': 'Movies',
'data': series_2}
series_3_output = {'name': 'Music',
'data': series_3}
output = {'categories': categories,
'series': [series_1_output]}
'series': [series_1_output, series_2_output, series_3_output]}
return output
def get_total_plays_per_month(self, y_axis='plays'):
@@ -226,7 +272,8 @@ class Graphs(object):
if y_axis == 'plays':
query = 'SELECT strftime("%Y-%m", datetime(started, "unixepoch", "localtime")) as datestring, ' \
'SUM(case when media_type = "episode" then 1 else 0 end) as tv_count, ' \
'SUM(case when media_type = "movie" then 1 else 0 end) as movie_count ' \
'SUM(case when media_type = "movie" then 1 else 0 end) as movie_count, ' \
'SUM(case when media_type = "track" then 1 else 0 end) as music_count ' \
'FROM session_history ' \
'WHERE datetime(started, "unixepoch", "localtime") >= datetime("now", "-12 months", "localtime") ' \
'GROUP BY strftime("%Y-%m", datetime(started, "unixepoch", "localtime")) ' \
@@ -235,8 +282,12 @@ class Graphs(object):
result = monitor_db.select(query)
else:
query = 'SELECT strftime("%Y-%m", datetime(started, "unixepoch", "localtime")) as datestring, ' \
'SUM(case when media_type = "episode" and stopped > 0 then (stopped - started) else 0 end) as tv_duration, ' \
'SUM(case when media_type = "movie" and stopped > 0 then (stopped - started) else 0 end) as movie_duration ' \
'SUM(case when media_type = "episode" and stopped > 0 then (stopped - started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as tv_duration, ' \
'SUM(case when media_type = "movie" and stopped > 0 then (stopped - started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as movie_duration, ' \
'SUM(case when media_type = "track" and stopped > 0 then (stopped - started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as music_duration ' \
'FROM session_history ' \
'WHERE datetime(started, "unixepoch", "localtime") >= datetime("now", "-12 months", "localtime") ' \
'GROUP BY strftime("%Y-%m", datetime(started, "unixepoch", "localtime")) ' \
@@ -254,6 +305,7 @@ class Graphs(object):
categories = []
series_1 = []
series_2 = []
series_3 = []
for month_item in sorted(month_range):
dt = datetime.datetime(*month_item[:6])
@@ -262,25 +314,31 @@ class Graphs(object):
categories.append(dt.strftime('%b %Y'))
series_1_value = 0
series_2_value = 0
series_3_value = 0
for item in result:
if date_string == item[0]:
series_1_value = item[1]
series_2_value = item[2]
series_3_value = item[3]
break
else:
series_1_value = 0
series_2_value = 0
series_3_value = 0
series_1.append(series_1_value)
series_2.append(series_2_value)
series_3.append(series_3_value)
series_1_output = {'name': 'TV',
'data': series_1}
series_2_output = {'name': 'Movies',
'data': series_2}
series_3_output = {'name': 'Music',
'data': series_3}
output = {'categories': categories,
'series': [series_1_output, series_2_output]}
'series': [series_1_output, series_2_output, series_3_output]}
return output
def get_total_plays_by_top_10_platforms(self, time_range='30', y_axis='plays'):
@@ -291,43 +349,64 @@ class Graphs(object):
if y_axis == 'plays':
query = 'SELECT platform, ' \
'count(id) as platform_count ' \
'SUM(case when media_type = "episode" then 1 else 0 end) as tv_count, ' \
'SUM(case when media_type = "movie" then 1 else 0 end) as movie_count, ' \
'SUM(case when media_type = "track" then 1 else 0 end) as music_count, ' \
'COUNT(id) as total_count ' \
'FROM session_history ' \
'WHERE (datetime(stopped, "unixepoch", "localtime") >= ' \
'datetime("now", "-' + time_range + ' days", "localtime")) AND ' \
'(media_type = "episode" OR media_type = "movie") ' \
'datetime("now", "-' + time_range + ' days", "localtime")) ' \
'GROUP BY platform ' \
'ORDER BY platform_count DESC ' \
'ORDER BY total_count DESC ' \
'LIMIT 10'
result = monitor_db.select(query)
y_axis_label = 'Total plays'
else:
query = 'SELECT platform, ' \
'SUM(case when stopped > 0 then (stopped - started) else 0 end) as duration ' \
'SUM(case when media_type = "episode" and stopped > 0 then (stopped - started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as tv_duration, ' \
'SUM(case when media_type = "movie" and stopped > 0 then (stopped - started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as movie_duration, ' \
'SUM(case when media_type = "track" and stopped > 0 then (stopped - started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as music_duration, ' \
'SUM(case when stopped > 0 then (stopped - started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as total_duration ' \
'FROM session_history ' \
'WHERE (datetime(stopped, "unixepoch", "localtime") >= ' \
'datetime("now", "-' + time_range + ' days", "localtime")) AND ' \
'(media_type = "episode" OR media_type = "movie") ' \
'datetime("now", "-' + time_range + ' days", "localtime")) ' \
'GROUP BY platform ' \
'ORDER BY duration DESC ' \
'ORDER BY total_duration DESC ' \
'LIMIT 10'
result = monitor_db.select(query)
y_axis_label = 'Total duration'
categories = []
series_1 = []
series_2 = []
series_3 = []
for item in result:
categories.append(item[0])
series_1.append(item[1])
series_2.append(item[2])
series_3.append(item[3])
series_1_output = {'name': y_axis_label,
# Rename Mystery platform names
platform_names = [('Mystery 3', 'Playstation 3'),
('Mystery 4', 'Playstation 4'),
('Mystery 5', 'Xbox 360')]
for old_name, new_name in platform_names:
categories = [item.replace(old_name, new_name) for item in categories]
series_1_output = {'name': 'TV',
'data': series_1}
series_2_output = {'name': 'Movies',
'data': series_2}
series_3_output = {'name': 'Music',
'data': series_3}
output = {'categories': categories,
'series': [series_1_output]}
'series': [series_1_output, series_2_output, series_3_output]}
return output
def get_total_plays_by_top_10_users(self, time_range='30', y_axis='plays'):
@@ -340,47 +419,61 @@ class Graphs(object):
query = 'SELECT ' \
'(case when users.friendly_name is null then session_history.user else ' \
'users.friendly_name end) as friendly_name,' \
'count(session_history.id) as user_count ' \
'SUM(case when media_type = "episode" then 1 else 0 end) as tv_count, ' \
'SUM(case when media_type = "movie" then 1 else 0 end) as movie_count, ' \
'SUM(case when media_type = "track" then 1 else 0 end) as music_count, ' \
'COUNT(session_history.id) as total_count ' \
'FROM session_history ' \
'JOIN users on session_history.user_id = users.user_id ' \
'WHERE (datetime(session_history.stopped, "unixepoch", "localtime") >= ' \
'datetime("now", "-' + time_range + ' days", "localtime")) AND ' \
'(session_history.media_type = "episode" OR session_history.media_type = "movie") ' \
'datetime("now", "-' + time_range + ' days", "localtime")) ' \
'GROUP BY session_history.user_id ' \
'ORDER BY user_count DESC ' \
'ORDER BY total_count DESC ' \
'LIMIT 10'
result = monitor_db.select(query)
y_axis_label = 'Total plays'
else:
query = 'SELECT ' \
'(case when users.friendly_name is null then session_history.user else ' \
'users.friendly_name end) as friendly_name,' \
'SUM(case when stopped > 0 then (stopped - started) else 0 end) as duration ' \
'SUM(case when media_type = "episode" and stopped > 0 then (stopped - started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as tv_duration, ' \
'SUM(case when media_type = "movie" and stopped > 0 then (stopped - started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as movie_duration, ' \
'SUM(case when media_type = "track" and stopped > 0 then (stopped - started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as music_duration, ' \
'SUM(case when stopped > 0 then (stopped - started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as total_duration ' \
'FROM session_history ' \
'JOIN users on session_history.user_id = users.user_id ' \
'WHERE (datetime(session_history.stopped, "unixepoch", "localtime") >= ' \
'datetime("now", "-' + time_range + ' days", "localtime")) AND ' \
'(session_history.media_type = "episode" OR session_history.media_type = "movie") ' \
'datetime("now", "-' + time_range + ' days", "localtime")) ' \
'GROUP BY session_history.user_id ' \
'ORDER BY duration DESC ' \
'ORDER BY total_duration DESC ' \
'LIMIT 10'
result = monitor_db.select(query)
y_axis_label = 'Total duration'
categories = []
series_1 = []
series_2 = []
series_3 = []
for item in result:
categories.append(item[0])
series_1.append(item[1])
series_2.append(item[2])
series_3.append(item[3])
series_1_output = {'name': y_axis_label,
series_1_output = {'name': 'TV',
'data': series_1}
series_2_output = {'name': 'Movies',
'data': series_2}
series_3_output = {'name': 'Music',
'data': series_3}
output = {'categories': categories,
'series': [series_1_output]}
'series': [series_1_output, series_2_output, series_3_output]}
return output
def get_total_plays_per_stream_type(self, time_range='30', y_axis='plays'):
@@ -392,31 +485,43 @@ class Graphs(object):
try:
if y_axis == 'plays':
query = 'SELECT date(session_history.started, "unixepoch", "localtime") as date_played, ' \
'SUM(case when session_history_media_info.video_decision = "direct play" then 1 else 0 end) as dp_count, ' \
'SUM(case when session_history_media_info.video_decision = "copy" then 1 else 0 end) as ds_count, ' \
'SUM(case when session_history_media_info.video_decision = "transcode" then 1 else 0 end) as tc_count ' \
'SUM(case when session_history_media_info.video_decision = "direct play" ' \
'or (session_history_media_info.video_decision = "" and session_history_media_info.audio_decision = "direct play") ' \
'then 1 else 0 end) as dp_count, ' \
'SUM(case when session_history_media_info.video_decision = "copy" ' \
'or (session_history_media_info.video_decision = "" and session_history_media_info.audio_decision = "copy") ' \
'then 1 else 0 end) as ds_count, ' \
'SUM(case when session_history_media_info.video_decision = "transcode" ' \
'or (session_history_media_info.video_decision = "" and session_history_media_info.audio_decision = "transcode") ' \
'then 1 else 0 end) as tc_count ' \
'FROM session_history ' \
'JOIN session_history_media_info ON session_history.id = session_history_media_info.id ' \
'WHERE (datetime(session_history.stopped, "unixepoch", "localtime") >= ' \
'datetime("now", "-%s days", "localtime")) AND ' \
'(session_history.media_type = "episode" OR session_history.media_type = "movie") ' \
'(session_history.media_type = "episode" OR session_history.media_type = "movie" OR session_history.media_type = "track") ' \
'GROUP BY date_played ' \
'ORDER BY started ASC' % time_range
result = monitor_db.select(query)
else:
query = 'SELECT date(session_history.started, "unixepoch", "localtime") as date_played, ' \
'SUM(case when session_history_media_info.video_decision = "direct play" AND ' \
'session_history.stopped > 0 then (stopped - started) else 0 end) as dp_duration, ' \
'SUM(case when session_history_media_info.video_decision = "copy" AND ' \
'session_history.stopped > 0 then (stopped - started) else 0 end) as ds_duration, ' \
'SUM(case when session_history_media_info.video_decision = "transcode" ' \
'AND session_history.stopped > 0 then (stopped - started) else 0 end) as tc_duration ' \
'SUM(case when (session_history_media_info.video_decision = "direct play" ' \
'or (session_history_media_info.video_decision = "" and session_history_media_info.audio_decision = "direct play")) ' \
'and session_history.stopped > 0 then (session_history.stopped - session_history.started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as dp_duration, ' \
'SUM(case when (session_history_media_info.video_decision = "copy" ' \
'or (session_history_media_info.video_decision = "" and session_history_media_info.audio_decision = "copy")) ' \
'and session_history.stopped > 0 then (session_history.stopped - session_history.started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as ds_duration, ' \
'SUM(case when (session_history_media_info.video_decision = "transcode" ' \
'or (session_history_media_info.video_decision = "" and session_history_media_info.audio_decision = "transcode")) ' \
'and session_history.stopped > 0 then (session_history.stopped - session_history.started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as tc_duration ' \
'FROM session_history ' \
'JOIN session_history_media_info ON session_history.id = session_history_media_info.id ' \
'WHERE datetime(session_history.stopped, "unixepoch", "localtime") >= ' \
'datetime("now", "-%s days", "localtime") AND ' \
'(session_history.media_type = "episode" OR session_history.media_type = "movie") ' \
'(session_history.media_type = "episode" OR session_history.media_type = "movie" OR session_history.media_type = "track") ' \
'GROUP BY date_played ' \
'ORDER BY started ASC' % time_range
@@ -465,7 +570,6 @@ class Graphs(object):
output = {'categories': categories,
'series': [series_1_output, series_2_output, series_3_output]}
return output
def get_total_plays_by_source_resolution(self, time_range='30', y_axis='plays'):
@@ -475,49 +579,74 @@ class Graphs(object):
time_range = '30'
if y_axis == 'plays':
query = 'SELECT ' \
'count(session_history.id) as play_count, ' \
'session_history_media_info.video_resolution AS resolution ' \
query = 'SELECT session_history_media_info.video_resolution AS resolution, ' \
'SUM(case when session_history_media_info.video_decision = "direct play" ' \
'or (session_history_media_info.video_decision = "" and session_history_media_info.audio_decision = "direct play") ' \
'then 1 else 0 end) as dp_count, ' \
'SUM(case when session_history_media_info.video_decision = "copy" ' \
'or (session_history_media_info.video_decision = "" and session_history_media_info.audio_decision = "copy") ' \
'then 1 else 0 end) as ds_count, ' \
'SUM(case when session_history_media_info.video_decision = "transcode" ' \
'or (session_history_media_info.video_decision = "" and session_history_media_info.audio_decision = "transcode") ' \
'then 1 else 0 end) as tc_count, ' \
'COUNT(session_history.id) as total_count ' \
'FROM session_history ' \
'JOIN session_history_media_info on session_history.id = session_history_media_info.id ' \
'WHERE (datetime(session_history.stopped, "unixepoch", "localtime") >= ' \
'datetime("now", "-' + time_range + ' days", "localtime")) AND ' \
'(session_history.media_type = "episode" OR session_history.media_type = "movie") ' \
'GROUP BY resolution ' \
'ORDER BY play_count DESC ' \
'ORDER BY total_count DESC ' \
'LIMIT 10'
result = monitor_db.select(query)
y_axis_label = 'Total plays'
else:
query = 'SELECT ' \
'SUM(case when stopped > 0 then (stopped - started) else 0 end) as duration, ' \
'session_history_media_info.video_resolution AS resolution ' \
query = 'SELECT session_history_media_info.video_resolution AS resolution,' \
'SUM(case when (session_history_media_info.video_decision = "direct play" ' \
'or (session_history_media_info.video_decision = "" and session_history_media_info.audio_decision = "direct play")) ' \
'and session_history.stopped > 0 then (session_history.stopped - session_history.started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as dp_duration, ' \
'SUM(case when (session_history_media_info.video_decision = "copy" ' \
'or (session_history_media_info.video_decision = "" and session_history_media_info.audio_decision = "copy")) ' \
'and session_history.stopped > 0 then (session_history.stopped - session_history.started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as ds_duration, ' \
'SUM(case when (session_history_media_info.video_decision = "transcode" ' \
'or (session_history_media_info.video_decision = "" and session_history_media_info.audio_decision = "transcode")) ' \
'and session_history.stopped > 0 then (session_history.stopped - session_history.started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as tc_duration, ' \
'SUM(case when stopped > 0 then (stopped - started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as total_duration ' \
'FROM session_history ' \
'JOIN session_history_media_info on session_history.id = session_history_media_info.id ' \
'WHERE (datetime(session_history.stopped, "unixepoch", "localtime") >= ' \
'datetime("now", "-' + time_range + ' days", "localtime")) AND ' \
'(session_history.media_type = "episode" OR session_history.media_type = "movie") ' \
'GROUP BY resolution ' \
'ORDER BY duration DESC ' \
'ORDER BY total_duration DESC ' \
'LIMIT 10'
result = monitor_db.select(query)
y_axis_label = 'Total duration'
categories = []
series_1 = []
series_2 = []
series_3 = []
for item in result:
categories.append(item[1])
series_1.append(item[0])
categories.append(item[0])
series_1.append(item[1])
series_2.append(item[2])
series_3.append(item[3])
series_1_output = {'name': y_axis_label,
series_1_output = {'name': 'Direct Play',
'data': series_1}
series_2_output = {'name': 'Direct Stream',
'data': series_2}
series_3_output = {'name': 'Transcode',
'data': series_3}
output = {'categories': categories,
'series': [series_1_output]}
'series': [series_1_output, series_2_output, series_3_output]}
return output
def get_total_plays_by_stream_resolution(self, time_range='30', y_axis='plays'):
@@ -528,7 +657,6 @@ class Graphs(object):
if y_axis == 'plays':
query = 'SELECT ' \
'count(session_history.id) as play_count, ' \
'(case when session_history_media_info.video_decision = "transcode" then ' \
'(case ' \
'when session_history_media_info.transcode_height <= 360 then "sd" ' \
@@ -538,21 +666,29 @@ class Graphs(object):
'when session_history_media_info.transcode_height <= 1080 then "1080" ' \
'when session_history_media_info.transcode_height <= 1440 then "QHD" ' \
'when session_history_media_info.transcode_height <= 2160 then "4K" ' \
'else "unknown" end) else session_history_media_info.video_resolution end) as resolution ' \
'else "unknown" end) else session_history_media_info.video_resolution end) as resolution, ' \
'SUM(case when session_history_media_info.video_decision = "direct play" ' \
'or (session_history_media_info.video_decision = "" and session_history_media_info.audio_decision = "direct play") ' \
'then 1 else 0 end) as dp_count, ' \
'SUM(case when session_history_media_info.video_decision = "copy" ' \
'or (session_history_media_info.video_decision = "" and session_history_media_info.audio_decision = "copy") ' \
'then 1 else 0 end) as ds_count, ' \
'SUM(case when session_history_media_info.video_decision = "transcode" ' \
'or (session_history_media_info.video_decision = "" and session_history_media_info.audio_decision = "transcode") ' \
'then 1 else 0 end) as tc_count, ' \
'COUNT(session_history.id) as total_count ' \
'FROM session_history ' \
'JOIN session_history_media_info on session_history.id = session_history_media_info.id ' \
'WHERE (datetime(session_history.stopped, "unixepoch", "localtime") >= ' \
'datetime("now", "-' + time_range + ' days", "localtime")) AND ' \
'(session_history.media_type = "episode" OR session_history.media_type = "movie") ' \
'GROUP BY resolution ' \
'ORDER BY play_count DESC ' \
'ORDER BY total_count DESC ' \
'LIMIT 10'
result = monitor_db.select(query)
y_axis_label = 'Total plays'
else:
query = 'SELECT ' \
'SUM(case when stopped > 0 then (stopped - started) else 0 end) as duration, ' \
'(case when session_history_media_info.video_decision = "transcode" then ' \
'(case ' \
'when session_history_media_info.transcode_height <= 360 then "sd" ' \
@@ -562,31 +698,137 @@ class Graphs(object):
'when session_history_media_info.transcode_height <= 1080 then "1080" ' \
'when session_history_media_info.transcode_height <= 1440 then "QHD" ' \
'when session_history_media_info.transcode_height <= 2160 then "4K" ' \
'else "unknown" end) else session_history_media_info.video_resolution end) as resolution ' \
'else "unknown" end) else session_history_media_info.video_resolution end) as resolution, ' \
'SUM(case when (session_history_media_info.video_decision = "direct play" ' \
'or (session_history_media_info.video_decision = "" and session_history_media_info.audio_decision = "direct play")) ' \
'and session_history.stopped > 0 then (session_history.stopped - session_history.started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as dp_duration, ' \
'SUM(case when (session_history_media_info.video_decision = "copy" ' \
'or (session_history_media_info.video_decision = "" and session_history_media_info.audio_decision = "copy")) ' \
'and session_history.stopped > 0 then (session_history.stopped - session_history.started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as ds_duration, ' \
'SUM(case when (session_history_media_info.video_decision = "transcode" ' \
'or (session_history_media_info.video_decision = "" and session_history_media_info.audio_decision = "transcode")) ' \
'and session_history.stopped > 0 then (session_history.stopped - session_history.started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as tc_duration, ' \
'SUM(case when stopped > 0 then (stopped - started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as total_duration ' \
'FROM session_history ' \
'JOIN session_history_media_info on session_history.id = session_history_media_info.id ' \
'WHERE (datetime(session_history.stopped, "unixepoch", "localtime") >= ' \
'datetime("now", "-' + time_range + ' days", "localtime")) AND ' \
'(session_history.media_type = "episode" OR session_history.media_type = "movie") ' \
'GROUP BY resolution ' \
'ORDER BY duration DESC ' \
'ORDER BY total_duration DESC ' \
'LIMIT 10'
result = monitor_db.select(query)
y_axis_label = 'Total duration'
categories = []
series_1 = []
series_2 = []
series_3 = []
for item in result:
categories.append(item[1])
series_1.append(item[0])
categories.append(item[0])
series_1.append(item[1])
series_2.append(item[2])
series_3.append(item[3])
series_1_output = {'name': y_axis_label,
series_1_output = {'name': 'Direct Play',
'data': series_1}
series_2_output = {'name': 'Direct Stream',
'data': series_2}
series_3_output = {'name': 'Transcode',
'data': series_3}
output = {'categories': categories,
'series': [series_1_output]}
'series': [series_1_output, series_2_output, series_3_output]}
return output
def get_stream_type_by_top_10_platforms(self, time_range='30', y_axis='plays'):
monitor_db = database.MonitorDatabase()
if not time_range.isdigit():
time_range = '30'
if y_axis == 'plays':
query = 'SELECT ' \
'session_history.platform as platform, ' \
'SUM(case when session_history_media_info.video_decision = "direct play" ' \
'or (session_history_media_info.video_decision = "" and session_history_media_info.audio_decision = "direct play") ' \
'then 1 else 0 end) as dp_count, ' \
'SUM(case when session_history_media_info.video_decision = "copy" ' \
'or (session_history_media_info.video_decision = "" and session_history_media_info.audio_decision = "copy") ' \
'then 1 else 0 end) as ds_count, ' \
'SUM(case when session_history_media_info.video_decision = "transcode" ' \
'or (session_history_media_info.video_decision = "" and session_history_media_info.audio_decision = "transcode") ' \
'then 1 else 0 end) as tc_count, ' \
'COUNT(session_history.id) as total_count ' \
'FROM session_history ' \
'JOIN session_history_media_info ON session_history.id = session_history_media_info.id ' \
'WHERE datetime(session_history.started, "unixepoch", "localtime") >= ' \
'datetime("now", "-' + time_range + ' days", "localtime") AND ' \
'(session_history.media_type = "episode" OR session_history.media_type = "movie" OR session_history.media_type = "track") ' \
'GROUP BY platform ' \
'ORDER BY total_count DESC LIMIT 10'
result = monitor_db.select(query)
else:
query = 'SELECT ' \
'session_history.platform as platform, ' \
'SUM(case when (session_history_media_info.video_decision = "direct play" ' \
'or (session_history_media_info.video_decision = "" and session_history_media_info.audio_decision = "direct play")) ' \
'and session_history.stopped > 0 then (session_history.stopped - session_history.started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as dp_duration, ' \
'SUM(case when (session_history_media_info.video_decision = "copy" ' \
'or (session_history_media_info.video_decision = "" and session_history_media_info.audio_decision = "copy")) ' \
'and session_history.stopped > 0 then (session_history.stopped - session_history.started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as ds_duration, ' \
'SUM(case when (session_history_media_info.video_decision = "transcode" ' \
'or (session_history_media_info.video_decision = "" and session_history_media_info.audio_decision = "transcode")) ' \
'and session_history.stopped > 0 then (session_history.stopped - session_history.started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as tc_duration, ' \
'SUM(case when session_history.stopped > 0 ' \
'then (session_history.stopped - session_history.started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as total_duration ' \
'FROM session_history ' \
'JOIN session_history_media_info ON session_history.id = session_history_media_info.id ' \
'WHERE datetime(session_history.started, "unixepoch", "localtime") >= ' \
'datetime("now", "-' + time_range + ' days", "localtime") AND ' \
'(session_history.media_type = "episode" OR session_history.media_type = "movie" OR session_history.media_type = "track") ' \
'GROUP BY platform ' \
'ORDER BY total_duration DESC LIMIT 10'
result = monitor_db.select(query)
categories = []
series_1 = []
series_2 = []
series_3 = []
for item in result:
categories.append(item[0])
series_1.append(item[1])
series_2.append(item[2])
series_3.append(item[3])
# Rename Mystery platform names
platform_names = [('Mystery 3', 'Playstation 3'),
('Mystery 4', 'Playstation 4'),
('Mystery 5', 'Xbox 360')]
for old_name, new_name in platform_names:
categories = [item.replace(old_name, new_name) for item in categories]
series_1_output = {'name': 'Direct Play',
'data': series_1}
series_2_output = {'name': 'Direct Stream',
'data': series_2}
series_3_output = {'name': 'Transcode',
'data': series_3}
output = {'categories': categories,
'series': [series_1_output, series_2_output, series_3_output]}
return output
@@ -599,15 +841,22 @@ class Graphs(object):
if y_axis == 'plays':
query = 'SELECT ' \
'CASE WHEN users.friendly_name is null then users.username else users.friendly_name end as username, ' \
'SUM(case when session_history_media_info.video_decision = "direct play" then 1 else 0 end) as dp_count, ' \
'SUM(case when session_history_media_info.video_decision = "copy" then 1 else 0 end) as ds_count, ' \
'SUM(case when session_history_media_info.video_decision = "transcode" then 1 else 0 end) as tr_count, ' \
'SUM(case when session_history.media_type != "track" then 1 else 0 end) as total_count ' \
'SUM(case when session_history_media_info.video_decision = "direct play" ' \
'or (session_history_media_info.video_decision = "" and session_history_media_info.audio_decision = "direct play") ' \
'then 1 else 0 end) as dp_count, ' \
'SUM(case when session_history_media_info.video_decision = "copy" ' \
'or (session_history_media_info.video_decision = "" and session_history_media_info.audio_decision = "copy") ' \
'then 1 else 0 end) as ds_count, ' \
'SUM(case when session_history_media_info.video_decision = "transcode" ' \
'or (session_history_media_info.video_decision = "" and session_history_media_info.audio_decision = "transcode") ' \
'then 1 else 0 end) as tc_count, ' \
'COUNT(session_history.id) as total_count ' \
'FROM session_history ' \
'JOIN users ON session_history.user_id = users.user_id ' \
'JOIN session_history_media_info ON session_history.id = session_history_media_info.id ' \
'WHERE datetime(session_history.started, "unixepoch", "localtime") >= ' \
'datetime("now", "-' + time_range + ' days", "localtime") ' \
'datetime("now", "-' + time_range + ' days", "localtime") AND ' \
'(session_history.media_type = "episode" OR session_history.media_type = "movie" OR session_history.media_type = "track") ' \
'GROUP BY username ' \
'ORDER BY total_count DESC LIMIT 10'
@@ -615,85 +864,29 @@ class Graphs(object):
else:
query = 'SELECT ' \
'CASE WHEN users.friendly_name is null then users.username else users.friendly_name end as username, ' \
'SUM(case when session_history.stopped > 0 AND session_history_media_info.video_decision = "direct play" ' \
'then (session_history.stopped - session_history.started) else 0 end) as dp_count, ' \
'SUM(case when session_history.stopped > 0 AND session_history_media_info.video_decision = "copy" ' \
'then (session_history.stopped - session_history.started) else 0 end) as ds_count, ' \
'SUM(case when session_history.stopped > 0 AND session_history_media_info.video_decision = "transcode" ' \
'then (session_history.stopped - session_history.started) else 0 end) as tr_count, ' \
'SUM(case when session_history.stopped > 0 AND session_history.media_type != "track" ' \
'then (session_history.stopped - session_history.started) else 0 end) as total_count ' \
'SUM(case when (session_history_media_info.video_decision = "direct play" ' \
'or (session_history_media_info.video_decision = "" and session_history_media_info.audio_decision = "direct play")) ' \
'and session_history.stopped > 0 then (session_history.stopped - session_history.started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as dp_duration, ' \
'SUM(case when (session_history_media_info.video_decision = "copy" ' \
'or (session_history_media_info.video_decision = "" and session_history_media_info.audio_decision = "copy")) ' \
'and session_history.stopped > 0 then (session_history.stopped - session_history.started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as ds_duration, ' \
'SUM(case when (session_history_media_info.video_decision = "transcode" ' \
'or (session_history_media_info.video_decision = "" and session_history_media_info.audio_decision = "transcode")) ' \
'and session_history.stopped > 0 then (session_history.stopped - session_history.started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as tc_duration, ' \
'SUM(case when session_history.stopped > 0 ' \
'then (session_history.stopped - session_history.started) ' \
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as total_duration ' \
'FROM session_history ' \
'JOIN users ON session_history.user_id = users.user_id ' \
'JOIN session_history_media_info ON session_history.id = session_history_media_info.id ' \
'WHERE datetime(session_history.started, "unixepoch", "localtime") >= ' \
'datetime("now", "-' + time_range + ' days", "localtime") ' \
'datetime("now", "-' + time_range + ' days", "localtime") AND ' \
'(session_history.media_type = "episode" OR session_history.media_type = "movie" OR session_history.media_type = "track") ' \
'GROUP BY username ' \
'ORDER BY total_count DESC LIMIT 10'
result = monitor_db.select(query)
categories = []
series_1 = []
series_2 = []
series_3 = []
for item in result:
categories.append(item[0])
series_1.append(item[1])
series_2.append(item[2])
series_3.append(item[3])
series_1_output = {'name': 'Direct Play',
'data': series_1}
series_2_output = {'name': 'Direct Stream',
'data': series_2}
series_3_output = {'name': 'Transcode',
'data': series_3}
output = {'categories': categories,
'series': [series_1_output, series_2_output, series_3_output]}
return output
def get_stream_type_by_top_10_platforms(self, time_range='30', y_axis='plays'):
monitor_db = database.MonitorDatabase()
if not time_range.isdigit():
time_range = '30'
if y_axis == 'plays':
query = 'SELECT ' \
'session_history.platform as platform, ' \
'SUM(case when session_history_media_info.video_decision = "direct play" then 1 else 0 end) as dp_count, ' \
'SUM(case when session_history_media_info.video_decision = "copy" then 1 else 0 end) as ds_count, ' \
'SUM(case when session_history_media_info.video_decision = "transcode" then 1 else 0 end) as tr_count, ' \
'SUM(case when session_history.media_type != "track" then 1 else 0 end) as total_count ' \
'FROM session_history ' \
'JOIN session_history_media_info ON session_history.id = session_history_media_info.id ' \
'WHERE datetime(session_history.started, "unixepoch", "localtime") >= ' \
'datetime("now", "-' + time_range + ' days", "localtime") ' \
'GROUP BY platform ' \
'ORDER BY total_count DESC LIMIT 10'
result = monitor_db.select(query)
else:
query = 'SELECT ' \
'session_history.platform as platform, ' \
'SUM(case when session_history.stopped > 0 AND session_history_media_info.video_decision = "direct play" ' \
'then (session_history.stopped - session_history.started) else 0 end) as dp_count, ' \
'SUM(case when session_history.stopped > 0 AND session_history_media_info.video_decision = "copy" ' \
'then (session_history.stopped - session_history.started) else 0 end) as ds_count, ' \
'SUM(case when session_history.stopped > 0 AND session_history_media_info.video_decision = "transcode" ' \
'then (session_history.stopped - session_history.started) else 0 end) as tr_count, ' \
'SUM(case when session_history.stopped > 0 AND session_history.media_type != "track" ' \
'then (session_history.stopped - session_history.started) else 0 end) as total_count ' \
'FROM session_history ' \
'JOIN session_history_media_info ON session_history.id = session_history_media_info.id ' \
'WHERE datetime(session_history.started, "unixepoch", "localtime") >= ' \
'datetime("now", "-' + time_range + ' days", "localtime") ' \
'GROUP BY platform ' \
'ORDER BY total_count DESC LIMIT 10'
'ORDER BY total_duration DESC LIMIT 10'
result = monitor_db.select(query)

View File

@@ -247,10 +247,10 @@ class MonitorProcessing(object):
else:
stopped = int(time.time())
if plexpy.CONFIG.VIDEO_LOGGING_ENABLE and \
if plexpy.CONFIG.VIDEO_LOGGING_ENABLE and str(session['rating_key']).isdigit() and \
(session['media_type'] == 'movie' or session['media_type'] == 'episode'):
logging_enabled = True
elif plexpy.CONFIG.MUSIC_LOGGING_ENABLE and \
elif plexpy.CONFIG.MUSIC_LOGGING_ENABLE and str(session['rating_key']).isdigit() and \
session['media_type'] == 'track':
logging_enabled = True
else:

View File

@@ -55,6 +55,7 @@ def extract_plexwatch_xml(xml=None):
parent_title = helpers.get_xml_attr(a, 'parentTitle')
studio = helpers.get_xml_attr(a, 'studio')
title = helpers.get_xml_attr(a, 'title')
tagline = helpers.get_xml_attr(a, 'tagline')
directors = []
if a.getElementsByTagName('Director'):
@@ -153,6 +154,7 @@ def extract_plexwatch_xml(xml=None):
'grandparent_title': grandparent_title,
'parent_title': parent_title,
'title': title,
'tagline': tagline,
'guid': guid,
'media_index': media_index,
'originally_available_at': originally_available_at,
@@ -356,6 +358,7 @@ def import_from_plexwatch(database=None, table_name=None, import_ignore_interval
'last_viewed_at': extracted_xml['last_viewed_at'],
'content_rating': row['content_rating'],
'summary': row['summary'],
'tagline': extracted_xml['tagline'],
'rating': extracted_xml['rating'],
'duration': extracted_xml['duration'],
'guid': extracted_xml['guid'],

View File

@@ -90,31 +90,14 @@ class PmsConnect(object):
return request
"""
Return list of seasons in requested show.
Return list of children in requested library item.
Parameters required: rating_key { ratingKey of parent }
Optional parameters: output_format { dict, json }
Output: array
"""
def get_season_list(self, rating_key='', output_format=''):
uri = '/library/metadata/' + rating_key + '/children'
request = self.request_handler.make_request(uri=uri,
proto=self.protocol,
request_type='GET',
output_format=output_format)
return request
"""
Return list of episodes in requested season.
Parameters required: rating_key { ratingKey of parent }
Optional parameters: output_format { dict, json }
Output: array
"""
def get_episode_list(self, rating_key='', output_format=''):
def get_children_list(self, rating_key='', output_format=''):
uri = '/library/metadata/' + rating_key + '/children'
request = self.request_handler.make_request(uri=uri,
proto=self.protocol,
@@ -381,6 +364,39 @@ class PmsConnect(object):
'actors': actors
}
metadata_list = {'metadata': metadata}
elif metadata_type == 'season':
parent_rating_key = helpers.get_xml_attr(metadata_main, 'parentRatingKey')
show_details = self.get_metadata_details(parent_rating_key)
metadata = {'type': metadata_type,
'rating_key': helpers.get_xml_attr(metadata_main, 'ratingKey'),
'parent_rating_key': helpers.get_xml_attr(metadata_main, 'parentRatingKey'),
'grandparent_title': helpers.get_xml_attr(metadata_main, 'grandparentTitle'),
'parent_index': helpers.get_xml_attr(metadata_main, 'parentIndex'),
'parent_title': helpers.get_xml_attr(metadata_main, 'parentTitle'),
'index': helpers.get_xml_attr(metadata_main, 'index'),
'studio': helpers.get_xml_attr(metadata_main, 'studio'),
'title': helpers.get_xml_attr(metadata_main, 'title'),
'content_rating': helpers.get_xml_attr(metadata_main, 'contentRating'),
'summary': show_details['metadata']['summary'],
'tagline': helpers.get_xml_attr(metadata_main, 'tagline'),
'rating': helpers.get_xml_attr(metadata_main, 'rating'),
'duration': show_details['metadata']['duration'],
'year': helpers.get_xml_attr(metadata_main, 'year'),
'thumb': helpers.get_xml_attr(metadata_main, 'thumb'),
'parent_thumb': helpers.get_xml_attr(metadata_main, 'parentThumb'),
'grandparent_thumb': helpers.get_xml_attr(metadata_main, 'grandparentThumb'),
'art': helpers.get_xml_attr(metadata_main, 'art'),
'originally_available_at': helpers.get_xml_attr(metadata_main, 'originallyAvailableAt'),
'added_at': helpers.get_xml_attr(metadata_main, 'addedAt'),
'updated_at': helpers.get_xml_attr(metadata_main, 'updatedAt'),
'last_viewed_at': helpers.get_xml_attr(metadata_main, 'lastViewedAt'),
'guid': helpers.get_xml_attr(metadata_main, 'guid'),
'genres': genres,
'actors': actors,
'writers': writers,
'directors': directors
}
metadata_list = {'metadata': metadata}
elif metadata_type == 'episode':
metadata = {'type': metadata_type,
'rating_key': helpers.get_xml_attr(metadata_main, 'ratingKey'),
@@ -443,9 +459,39 @@ class PmsConnect(object):
'directors': directors
}
metadata_list = {'metadata': metadata}
elif metadata_type == 'season':
elif metadata_type == 'artist':
metadata = {'type': metadata_type,
'rating_key': helpers.get_xml_attr(metadata_main, 'ratingKey'),
'grandparent_title': helpers.get_xml_attr(metadata_main, 'grandparentTitle'),
'parent_index': helpers.get_xml_attr(metadata_main, 'parentIndex'),
'parent_title': helpers.get_xml_attr(metadata_main, 'parentTitle'),
'index': helpers.get_xml_attr(metadata_main, 'index'),
'studio': helpers.get_xml_attr(metadata_main, 'studio'),
'title': helpers.get_xml_attr(metadata_main, 'title'),
'content_rating': helpers.get_xml_attr(metadata_main, 'contentRating'),
'summary': helpers.get_xml_attr(metadata_main, 'summary'),
'tagline': helpers.get_xml_attr(metadata_main, 'tagline'),
'rating': helpers.get_xml_attr(metadata_main, 'rating'),
'duration': helpers.get_xml_attr(metadata_main, 'duration'),
'year': helpers.get_xml_attr(metadata_main, 'year'),
'thumb': helpers.get_xml_attr(metadata_main, 'thumb'),
'parent_thumb': helpers.get_xml_attr(metadata_main, 'parentThumb'),
'grandparent_thumb': helpers.get_xml_attr(metadata_main, 'grandparentThumb'),
'art': helpers.get_xml_attr(metadata_main, 'art'),
'originally_available_at': helpers.get_xml_attr(metadata_main, 'originallyAvailableAt'),
'added_at': helpers.get_xml_attr(metadata_main, 'addedAt'),
'updated_at': helpers.get_xml_attr(metadata_main, 'updatedAt'),
'last_viewed_at': helpers.get_xml_attr(metadata_main, 'lastViewedAt'),
'guid': helpers.get_xml_attr(metadata_main, 'guid'),
'writers': writers,
'directors': directors,
'genres': genres,
'actors': actors
}
metadata_list = {'metadata': metadata}
elif metadata_type == 'album':
parent_rating_key = helpers.get_xml_attr(metadata_main, 'parentRatingKey')
show_details = self.get_metadata_details(parent_rating_key)
artist_details = self.get_metadata_details(parent_rating_key)
metadata = {'type': metadata_type,
'rating_key': helpers.get_xml_attr(metadata_main, 'ratingKey'),
'parent_rating_key': helpers.get_xml_attr(metadata_main, 'parentRatingKey'),
@@ -456,10 +502,10 @@ class PmsConnect(object):
'studio': helpers.get_xml_attr(metadata_main, 'studio'),
'title': helpers.get_xml_attr(metadata_main, 'title'),
'content_rating': helpers.get_xml_attr(metadata_main, 'contentRating'),
'summary': show_details['metadata']['summary'],
'summary': artist_details['metadata']['summary'],
'tagline': helpers.get_xml_attr(metadata_main, 'tagline'),
'rating': helpers.get_xml_attr(metadata_main, 'rating'),
'duration': show_details['metadata']['duration'],
'duration': helpers.get_xml_attr(metadata_main, 'duration'),
'year': helpers.get_xml_attr(metadata_main, 'year'),
'thumb': helpers.get_xml_attr(metadata_main, 'thumb'),
'parent_thumb': helpers.get_xml_attr(metadata_main, 'parentThumb'),
@@ -477,8 +523,12 @@ class PmsConnect(object):
}
metadata_list = {'metadata': metadata}
elif metadata_type == 'track':
parent_rating_key = helpers.get_xml_attr(metadata_main, 'parentRatingKey')
album_details = self.get_metadata_details(parent_rating_key)
metadata = {'type': metadata_type,
'rating_key': helpers.get_xml_attr(metadata_main, 'ratingKey'),
'parent_rating_key': helpers.get_xml_attr(metadata_main, 'parentRatingKey'),
'grandparent_rating_key': helpers.get_xml_attr(metadata_main, 'grandparentRatingKey'),
'grandparent_title': helpers.get_xml_attr(metadata_main, 'grandparentTitle'),
'parent_index': helpers.get_xml_attr(metadata_main, 'parentIndex'),
'parent_title': helpers.get_xml_attr(metadata_main, 'parentTitle'),
@@ -490,7 +540,7 @@ class PmsConnect(object):
'tagline': helpers.get_xml_attr(metadata_main, 'tagline'),
'rating': helpers.get_xml_attr(metadata_main, 'rating'),
'duration': helpers.get_xml_attr(metadata_main, 'duration'),
'year': helpers.get_xml_attr(metadata_main, 'year'),
'year': album_details['metadata']['year'],
'thumb': helpers.get_xml_attr(metadata_main, 'thumb'),
'parent_thumb': helpers.get_xml_attr(metadata_main, 'parentThumb'),
'grandparent_thumb': helpers.get_xml_attr(metadata_main, 'grandparentThumb'),
@@ -547,6 +597,12 @@ class PmsConnect(object):
for session in session_data:
session_output = self.get_session_each(session_type, session)
session_list.append(session_output)
if a.getElementsByTagName('Photo'):
session_data = a.getElementsByTagName('Photo')
session_type = 'photo'
for session in session_data:
session_output = self.get_session_each(session_type, session)
session_list.append(session_output)
output = {'stream_count': helpers.get_xml_attr(xml_head[0], 'size'),
'sessions': session_list
@@ -565,8 +621,8 @@ class PmsConnect(object):
def get_session_each(self, stream_type='', session=None):
session_output = None
user_data = users.Users()
if stream_type == 'track':
if stream_type == 'track':
media_info = session.getElementsByTagName('Media')[0]
audio_decision = 'direct play'
audio_channels = helpers.get_xml_attr(media_info, 'audioChannels')
@@ -654,6 +710,7 @@ class PmsConnect(object):
'type': 'track',
'indexes': 0
}
elif stream_type == 'video':
media_info = session.getElementsByTagName('Media')[0]
audio_decision = 'direct play'
@@ -886,92 +943,151 @@ class PmsConnect(object):
'type': helpers.get_xml_attr(session, 'type'),
'indexes': 0
}
elif stream_type == 'photo':
media_info = session.getElementsByTagName('Media')[0]
video_decision = 'direct play'
container = helpers.get_xml_attr(media_info, 'container')
aspect_ratio = helpers.get_xml_attr(media_info, 'aspectRatio')
width = helpers.get_xml_attr(media_info, 'width')
height = helpers.get_xml_attr(media_info, 'height')
if session.getElementsByTagName('TranscodeSession'):
transcode_session = session.getElementsByTagName('TranscodeSession')[0]
throttled = helpers.get_xml_attr(transcode_session, 'throttled')
transcode_progress = helpers.get_xml_attr(transcode_session, 'progress')
transcode_speed = helpers.get_xml_attr(transcode_session, 'speed')
video_decision = helpers.get_xml_attr(transcode_session, 'videoDecision')
transcode_video_codec = helpers.get_xml_attr(transcode_session, 'videoCodec')
transcode_width = helpers.get_xml_attr(transcode_session, 'width')
transcode_height = helpers.get_xml_attr(transcode_session, 'height')
transcode_container = helpers.get_xml_attr(transcode_session, 'container')
transcode_protocol = helpers.get_xml_attr(transcode_session, 'protocol')
else:
throttled = '0'
transcode_progress = '0'
transcode_speed = ''
transcode_video_codec = ''
transcode_width = ''
transcode_height = ''
transcode_container = ''
transcode_protocol = ''
user_details = user_data.get_user_details(
user=helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title'))
if helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'machineIdentifier').endswith('_Photo'):
machine_id = helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'machineIdentifier')[:-6]
else:
machine_id = helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'machineIdentifier')
session_output = {'session_key': helpers.get_xml_attr(session, 'sessionKey'),
'media_index': helpers.get_xml_attr(session, 'index'),
'parent_media_index': helpers.get_xml_attr(session, 'parentIndex'),
'art': helpers.get_xml_attr(session, 'art'),
'parent_thumb': helpers.get_xml_attr(session, 'parentThumb'),
'grandparent_thumb': helpers.get_xml_attr(session, 'grandparentThumb'),
'thumb': helpers.get_xml_attr(session, 'thumb'),
'bif_thumb': '',
'user': user_details['username'],
'user_id': user_details['user_id'],
'friendly_name': user_details['friendly_name'],
'user_thumb': user_details['thumb'],
'player': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'title'),
'platform': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'platform'),
'machine_id': machine_id,
'state': helpers.get_xml_attr(session.getElementsByTagName('Player')[0], 'state'),
'grandparent_title': helpers.get_xml_attr(session, 'grandparentTitle'),
'parent_title': helpers.get_xml_attr(session, 'parentTitle'),
'title': helpers.get_xml_attr(session, 'title'),
'year': helpers.get_xml_attr(session, 'year'),
'rating_key': helpers.get_xml_attr(session, 'ratingKey'),
'parent_rating_key': helpers.get_xml_attr(session, 'parentRatingKey'),
'grandparent_rating_key': helpers.get_xml_attr(session, 'grandparentRatingKey'),
'throttled': throttled,
'transcode_progress': transcode_progress,
'transcode_speed': str(round(helpers.cast_to_float(transcode_speed), 1)),
'audio_decision': '',
'audio_channels': '',
'audio_codec': '',
'video_decision': video_decision,
'video_codec': '',
'height': height,
'width': width,
'container': container,
'bitrate': '',
'video_resolution': '',
'video_framerate': '',
'aspect_ratio': aspect_ratio,
'transcode_audio_channels': '',
'transcode_audio_codec': '',
'transcode_video_codec': transcode_video_codec,
'transcode_width': transcode_width,
'transcode_height': transcode_height,
'transcode_container': transcode_container,
'transcode_protocol': transcode_protocol,
'duration': '',
'progress': '',
'progress_percent': '100',
'type': 'photo',
'indexes': 0
}
else:
logger.warn(u"No known stream types found in session list.")
return session_output
"""
Return processed and validated season list.
Return processed and validated children list.
Output: array
"""
def get_show_children(self, rating_key=''):
season_data = self.get_season_list(rating_key, output_format='xml')
def get_item_children(self, rating_key=''):
children_data = self.get_children_list(rating_key, output_format='xml')
try:
xml_head = season_data.getElementsByTagName('MediaContainer')
xml_head = children_data.getElementsByTagName('MediaContainer')
except:
logger.warn("Unable to parse XML for get_season_list.")
logger.warn("Unable to parse XML for get_children_list.")
return []
season_list = []
children_list = []
for a in xml_head:
if a.getAttribute('size'):
if a.getAttribute('size') == '0':
logger.debug(u"No season data.")
season_list = {'season_count': '0',
'season_list': []
}
return season_list
logger.debug(u"No children data.")
children_list = {'children_count': '0',
'children_list': []
}
return parent_list
result_data = []
if a.getElementsByTagName('Directory'):
result_data = a.getElementsByTagName('Directory')
for result in result_data:
season_output = {'rating_key': helpers.get_xml_attr(result, 'ratingKey'),
'index': helpers.get_xml_attr(result, 'index'),
'title': helpers.get_xml_attr(result, 'title'),
'thumb': helpers.get_xml_attr(result, 'thumb'),
'parent_thumb': helpers.get_xml_attr(a, 'thumb')
}
season_list.append(season_output)
output = {'season_count': helpers.get_xml_attr(xml_head[0], 'size'),
'title': helpers.get_xml_attr(xml_head[0], 'title2'),
'season_list': season_list
}
return output
"""
Return processed and validated episode list.
Output: array
"""
def get_season_children(self, rating_key=''):
episode_data = self.get_episode_list(rating_key, output_format='xml')
try:
xml_head = episode_data.getElementsByTagName('MediaContainer')
except:
logger.warn("Unable to parse XML for get_episode_list.")
return []
episode_list = []
for a in xml_head:
if a.getAttribute('size'):
if a.getAttribute('size') == '0':
logger.debug(u"No episode data.")
episode_list = {'episode_count': '0',
'episode_list': []
}
return episode_list
if a.getElementsByTagName('Video'):
result_data = a.getElementsByTagName('Video')
for result in result_data:
episode_output = {'rating_key': helpers.get_xml_attr(result, 'ratingKey'),
'index': helpers.get_xml_attr(result, 'index'),
'title': helpers.get_xml_attr(result, 'title'),
'thumb': helpers.get_xml_attr(result, 'thumb')
}
episode_list.append(episode_output)
if a.getElementsByTagName('Track'):
result_data = a.getElementsByTagName('Track')
output = {'episode_count': helpers.get_xml_attr(xml_head[0], 'size'),
if result_data:
for result in result_data:
children_output = {'rating_key': helpers.get_xml_attr(result, 'ratingKey'),
'index': helpers.get_xml_attr(result, 'index'),
'title': helpers.get_xml_attr(result, 'title'),
'thumb': helpers.get_xml_attr(result, 'thumb'),
'parent_thumb': helpers.get_xml_attr(a, 'thumb'),
'duration': helpers.get_xml_attr(result, 'duration')
}
children_list.append(children_output)
output = {'children_count': helpers.get_xml_attr(xml_head[0], 'size'),
'children_type': helpers.get_xml_attr(xml_head[0], 'viewGroup'),
'title': helpers.get_xml_attr(xml_head[0], 'title2'),
'episode_list': episode_list
'children_list': children_list
}
return output

View File

@@ -1,2 +1,2 @@
PLEXPY_VERSION = "master"
PLEXPY_RELEASE_VERSION = "1.1.7"
PLEXPY_RELEASE_VERSION = "1.1.9"

View File

@@ -762,6 +762,10 @@ class WebInterface(object):
def info(self, item_id=None, source=None, **kwargs):
metadata = None
config = {
"pms_identifier": plexpy.CONFIG.PMS_IDENTIFIER
}
if source == 'history':
data_factory = datafactory.DataFactory()
metadata = data_factory.get_metadata_details(row_id=item_id)
@@ -772,7 +776,7 @@ class WebInterface(object):
metadata = result['metadata']
if metadata:
return serve_template(templatename="info.html", data=metadata, title="Info")
return serve_template(templatename="info.html", data=metadata, title="Info", config=config)
else:
logger.warn('Unable to retrieve data.')
return serve_template(templatename="info.html", data=None, title="Info")
@@ -817,28 +821,16 @@ class WebInterface(object):
return serve_template(templatename="user_platform_stats.html", data=None, title="Platform Stats")
@cherrypy.expose
def get_show_children(self, rating_key='', **kwargs):
def get_item_children(self, rating_key='', **kwargs):
pms_connect = pmsconnect.PmsConnect()
result = pms_connect.get_show_children(rating_key)
result = pms_connect.get_item_children(rating_key)
if result:
return serve_template(templatename="info_season_list.html", data=result, title="Season List")
return serve_template(templatename="info_children_list.html", data=result, title="Children List")
else:
logger.warn('Unable to retrieve data.')
return serve_template(templatename="info_season_list.html", data=None, title="Season List")
@cherrypy.expose
def get_season_children(self, rating_key='', **kwargs):
pms_connect = pmsconnect.PmsConnect()
result = pms_connect.get_season_children(rating_key)
if result:
return serve_template(templatename="info_episode_list.html", data=result, title="Episode List")
else:
logger.warn('Unable to retrieve data.')
return serve_template(templatename="info_episode_list.html", data=None, title="Episode List")
return serve_template(templatename="info_children_list.html", data=None, title="Children List")
@cherrypy.expose
def get_metadata_json(self, rating_key='', **kwargs):