Compare commits

...

30 Commits

Author SHA1 Message Date
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
Tim
3fcc44aacf Merge branch 'dev' 2015-09-07 21:16:30 +02:00
Tim
fcc4575a86 v1.1.7 2015-09-07 21:15:52 +02:00
Tim
ebd0276eae Fix bug when parsing custom notification strings with unicode characters. 2015-09-07 20:43:15 +02:00
drzoidberg33
35521e127f Merge pull request #163 from JonnyWong16/miscellaneous-fixes
Fix for 5 digit library stats
2015-09-07 19:22:04 +02:00
Jonathan Wong
2c83554631 Update documentation 2015-09-06 21:13:56 -07:00
Jonathan Wong
56b717b1a1 Add transcode progress and speed to dashboard activity 2015-09-06 21:10:47 -07:00
Jonathan Wong
56f601e2a5 Add icon for play/pause/buffer state in dashboard activity 2015-09-06 15:52:47 -07:00
Jonathan Wong
3867dd7bdd Add throttled indicator to dashboard activity 2015-09-06 15:51:46 -07:00
Jonathan Wong
b7dc28c3fb Remove unnecessary console.log 2015-09-06 13:33:35 -07:00
Jonathan Wong
e6383d52ad Fix adding tagline to session_history_metadata table 2015-09-06 13:21:08 -07:00
Jonathan Wong
0a2ebb8815 Add tagline for newly watched items 2015-09-06 12:57:51 -07:00
Jonathan Wong
e44a0fed22 Fix tagline only if type is movie 2015-09-06 12:46:46 -07:00
Jonathan Wong
2d7585d64b Add tagline to movie info metadata 2015-09-06 12:31:50 -07:00
Jonathan Wong
df290d995b Make video preview thumbnails wording clearer. 2015-09-06 12:17:55 -07:00
Jonathan Wong
36ee5234b1 Revert overflow: hidden
* Accidentally hid top stats slider.
2015-09-06 11:54:31 -07:00
Jonathan Wong
48e601d5ff Restore edit username in users table
* Editing usernames was accidentally removed in e7b1e17
2015-09-06 11:20:49 -07:00
Jonathan Wong
84aa727387 Fix for 5 digit library stats 2015-09-06 11:03:47 -07:00
Tim
29204cb6ba Fix weird issue with bad merge. 2015-09-06 15:33:17 +02:00
19 changed files with 329 additions and 125 deletions

View File

@@ -1,5 +1,25 @@
# Changelog # Changelog
## 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.
* Add play/pause/buffer icon to activity pane. Thanks @JonnyWong.
* Add transcoder info in activity pane info. Thanks @JonnyWong.
* Show transcoder progress on activity progress bar. Thanks @JonnyWong.
* Fix bug where custom notification strings would be ignored if unicode characters were present.
* Fix text overflow issue on home stats cards. Thanks @JonnyWong.
* Fix regression with user friendly name change input in edit screen. Thanks @JonnyWong.
## v1.1.6 (2015-09-06) ## v1.1.6 (2015-09-06)
* Home stats cards are now expandable to show multiple items. Configurable in settings. Thanks @JonnyWong. * Home stats cards are now expandable to show multiple items. Configurable in settings. Thanks @JonnyWong.

View File

@@ -1,5 +1,7 @@
#PlexPy #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). 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). This project is based on code from Headphones (https://github.com/rembo10/headphones) and PlexWatchWeb (https://github.com/ecleese/plexWatchWeb).

View File

@@ -683,6 +683,13 @@ a:hover .dashboard-activity-poster {
-webkit-transition: all 0s; -webkit-transition: all 0s;
transition: all 0s; transition: all 0s;
} }
.dashboard-activity-progress .bufferbar {
padding-top: 6px;
background-color: #444;
position: absolute;
height: 6px;
overflow: hidden;
}
.dashboard-activity-progress .bar { .dashboard-activity-progress .bar {
padding-top: 6px; padding-top: 6px;
background-color: #faa732; background-color: #faa732;
@@ -693,6 +700,9 @@ a:hover .dashboard-activity-poster {
background-image: linear-gradient(to bottom, #fbb450, #f89406); background-image: linear-gradient(to bottom, #fbb450, #f89406);
background-repeat: repeat-x; background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);
position: absolute;
height: 6px;
overflow: hidden;
} }
.dashboard-activity-metadata-wrapper { .dashboard-activity-metadata-wrapper {
position: relative; position: relative;
@@ -963,11 +973,40 @@ a .dashboard-activity-metadata-user-thumb:hover {
overflow: hidden; overflow: hidden;
z-index: 1; z-index: 1;
} }
a .summary-poster-face:hover, .summary-poster-face-overlay {
a .summary-poster-face-episode:hover { 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; webkit-box-shadow: inset 0 0 0 2px #e9a049;
-moz-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; 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(/interfaces/default/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 .summary-poster-face-overlay span,
a:hover .summary-poster-face-episode .summary-poster-face-overlay span {
opacity: 1;
} }
.summary-content-padding { .summary-content-padding {
float: left; float: left;
@@ -1541,6 +1580,7 @@ a .season-episodes-card-overlay:hover {
-webkit-box-shadow: 0 0 4px rgba(0,0,0,.3),inset 0 0 0 1px rgba(255,255,255,.1); -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); -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); box-shadow: 0 0 4px rgba(0,0,0,.3),inset 0 0 0 1px rgba(255,255,255,.1);
white-space: nowrap;
} }
.home-platforms-instance li { .home-platforms-instance li {
position: relative; position: relative;
@@ -1553,7 +1593,6 @@ a .season-episodes-card-overlay:hover {
height: 120px; height: 120px;
} }
.home-platforms-instance-name { .home-platforms-instance-name {
float: left;
color: #fff; color: #fff;
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
@@ -1565,53 +1604,21 @@ a .season-episodes-card-overlay:hover {
padding: 0 0 0 20px; padding: 0 0 0 20px;
} }
.home-platforms-instance-name h4 { .home-platforms-instance-name h4 {
margin: 10px 0 20px 0; margin: 10px 0 4px 0;
}
.home-platforms-instance-name h5 {
font-size: 14px;
line-height: 16px;
margin: 15px 0 2px 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.home-platforms-instance-name2 {
position: absolute;
top: 34px;
left: 215px;
}
.home-platforms-instance-name2 h5 {
font-size: 14px;
line-height: 16px;
margin: 15px 0 2px 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.home-platforms-instance-name2 h3 {
font-size: 30px;
font-weight: bold;
color: #F9AA03;
line-height: 22px;
position: relative;
top: 5px;
margin: 0 5px 0 0;
padding-top: 6px;
float: left;
}
.home-platforms-instance-name2 p {
color: #aaa;
font-size: 12px;
float: left;
position: relative;
top: 21px;
left: 0px;
} }
.home-platforms-instance-playcount { .home-platforms-instance-playcount {
float: left; display: inline-block;
position: relative; position: relative;
padding: 6px 0 0 20px; padding: 6px 0 0 20px;
width: 100%; max-width: 100%;
}
.home-platforms-instance-playcount h4 {
font-size: 14px;
line-height: 16px;
margin: 10px 0 10px 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
} }
.home-platforms-instance-playcount h3 { .home-platforms-instance-playcount h3 {
font-size: 30px; font-size: 30px;
@@ -1638,6 +1645,14 @@ a .season-episodes-card-overlay:hover {
padding: 6px 0 0 20px; padding: 6px 0 0 20px;
width: 100%; width: 100%;
} }
.home-platforms-instance-last-user h4 {
font-size: 14px;
line-height: 16px;
margin: 10px 0 10px 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.home-platforms-instance-last-user h5 { .home-platforms-instance-last-user h5 {
font-size: 12px; font-size: 12px;
position: relative; position: relative;
@@ -2220,6 +2235,9 @@ a .home-platforms-instance-list-oval:hover,
color: #fff; color: #fff;
cursor: pointer; cursor: pointer;
} }
.edit-user-name > input[type='text'] {
margin: 0;
}
.popover { .popover {
z-index: 2; z-index: 2;
} }

View File

@@ -34,6 +34,9 @@ title Returns the name of the episode, movie or music trac
year Returns the year of the episode, movie, or clip. year Returns the year of the episode, movie, or clip.
player Returns the name of the platform used to play the stream. player Returns the name of the platform used to play the stream.
platform Returns the type of platform used to play the stream. platform Returns the type of platform used to play the stream.
throttled Returns true if the transcode session is throttled.
transcode_progress Returns the current transcode progress of the item. 0 to 100.
transcode_speed Returns the current transcode speed of the item.
audio_decision Returns the audio transcode decision. Either 'transcode', 'copy' or 'direct play'. audio_decision Returns the audio transcode decision. Either 'transcode', 'copy' or 'direct play'.
audio_codec Returns the name of the audio codec. audio_codec Returns the name of the audio codec.
audio_channels Returns the number of audio channels. audio_channels Returns the number of audio channels.
@@ -68,7 +71,6 @@ DOCUMENTATION :: END
<a href="info?item_id=${a['rating_key']}"> <a href="info?item_id=${a['rating_key']}">
% endif % endif
<div class="dashboard-activity-poster"> <div class="dashboard-activity-poster">
<script>console.log('${a['indexes']}');</script>
% if a['type'] == 'movie' and not a['indexes']: % if a['type'] == 'movie' and not a['indexes']:
<div class="dashboard-activity-poster-face" style="background-image: url(pms_image_proxy?img=${a['art']}&width=500&height=280);"></div> <div class="dashboard-activity-poster-face" style="background-image: url(pms_image_proxy?img=${a['art']}&width=500&height=280);"></div>
% elif a['type'] == 'episode' and not a['indexes']: % elif a['type'] == 'episode' and not a['indexes']:
@@ -116,7 +118,12 @@ DOCUMENTATION :: END
% if a['audio_decision'] == 'direct play': % if a['audio_decision'] == 'direct play':
Stream &nbsp;<strong>Direct Play</strong> Stream &nbsp;<strong>Direct Play</strong>
% else: % else:
Stream &nbsp;<strong>Transcoding</strong> Stream &nbsp;<strong>Transcoding
(Speed: ${a['transcode_speed']})
% if a['throttled'] == '1':
(Throttled)
% endif
</strong>
% endif % endif
<br /> <br />
% if a['audio_decision'] == 'direct play': % if a['audio_decision'] == 'direct play':
@@ -130,7 +137,12 @@ DOCUMENTATION :: END
% if a['video_decision'] == 'direct play': % if a['video_decision'] == 'direct play':
Stream &nbsp;<strong>Direct Play</strong> Stream &nbsp;<strong>Direct Play</strong>
% else: % else:
Stream &nbsp;<strong>Transcoding</strong> Stream &nbsp;<strong>Transcoding
(Speed: ${a['transcode_speed']})
% if a['throttled'] == '1':
(Throttled)
% endif
</strong>
% endif % endif
<br /> <br />
% if a['video_decision'] == 'direct play': % if a['video_decision'] == 'direct play':
@@ -163,6 +175,7 @@ DOCUMENTATION :: END
% endif % endif
<div class="dashboard-activity-progress"> <div class="dashboard-activity-progress">
<div class="dashboard-activity-progress-bar"> <div class="dashboard-activity-progress-bar">
<div class="bufferbar" style="width: ${a['transcode_progress']}%">${a['transcode_progress']}%</div>
<div class="bar" style="width: ${a['progress_percent']}%">${a['progress_percent']}%</div> <div class="bar" style="width: ${a['progress_percent']}%">${a['progress_percent']}%</div>
</div> </div>
</div> </div>
@@ -171,6 +184,13 @@ DOCUMENTATION :: END
<div class="dashboard-activity-metadata-user-thumb" style="background-image: url(${a['user_thumb']});"></div> <div class="dashboard-activity-metadata-user-thumb" style="background-image: url(${a['user_thumb']});"></div>
</a> </a>
<div class="dashboard-activity-metadata-title"> <div class="dashboard-activity-metadata-title">
% if a['state'] == 'playing':
<i class="fa fa-play"></i>&nbsp;
% elif a['state'] == 'paused':
<i class="fa fa-pause"></i>&nbsp;
% elif a['state'] == 'buffering':
<i class="fa fa-spinner"></i>&nbsp;
% endif
% if a['type'] == 'episode': % if a['type'] == 'episode':
<a href="info?item_id=${a['rating_key']}">${a['grandparent_title']} - ${a['title']}</a> <a href="info?item_id=${a['rating_key']}">${a['grandparent_title']} - ${a['title']}</a>
% elif a['type'] == 'movie': % elif a['type'] == 'movie':

View File

@@ -73,13 +73,13 @@ DOCUMENTATION :: END
<div class="home-platforms-instance-info"> <div class="home-platforms-instance-info">
<div class="home-platforms-instance-name"> <div class="home-platforms-instance-name">
<h4>Most Watched TV</h4> <h4>Most Watched TV</h4>
<h5> </div>
<div class="home-platforms-instance-playcount">
<h4>
<a href="info?item_id=${top_stat['rows'][0]['rating_key']}"> <a href="info?item_id=${top_stat['rows'][0]['rating_key']}">
${top_stat['rows'][0]['title']} ${top_stat['rows'][0]['title']}
</a> </a>
</h5> </h4>
</div>
<div class="home-platforms-instance-playcount">
% if top_stat['stat_type'] == 'total_plays': % if top_stat['stat_type'] == 'total_plays':
<h3>${top_stat['rows'][0]['total_plays']}</h3> <h3>${top_stat['rows'][0]['total_plays']}</h3>
<p> plays</p> <p> plays</p>
@@ -153,13 +153,13 @@ DOCUMENTATION :: END
<div class="home-platforms-instance-info"> <div class="home-platforms-instance-info">
<div class="home-platforms-instance-name"> <div class="home-platforms-instance-name">
<h4>Most Popular TV</h4> <h4>Most Popular TV</h4>
<h5> </div>
<div class="home-platforms-instance-playcount">
<h4>
<a href="info?item_id=${top_stat['rows'][0]['rating_key']}"> <a href="info?item_id=${top_stat['rows'][0]['rating_key']}">
${top_stat['rows'][0]['title']} ${top_stat['rows'][0]['title']}
</a> </a>
</h5> </h4>
</div>
<div class="home-platforms-instance-playcount">
<h3>${top_stat['rows'][0]['users_watched']}</h3> <h3>${top_stat['rows'][0]['users_watched']}</h3>
<p> users</p> <p> users</p>
</div> </div>
@@ -225,13 +225,13 @@ DOCUMENTATION :: END
<div class="home-platforms-instance-info"> <div class="home-platforms-instance-info">
<div class="home-platforms-instance-name"> <div class="home-platforms-instance-name">
<h4>Most Watched Movie</h4> <h4>Most Watched Movie</h4>
<h5> </div>
<div class="home-platforms-instance-playcount">
<h4>
<a href="info?item_id=${top_stat['rows'][0]['rating_key']}"> <a href="info?item_id=${top_stat['rows'][0]['rating_key']}">
${top_stat['rows'][0]['title']} ${top_stat['rows'][0]['title']}
</a> </a>
</h5> </h4>
</div>
<div class="home-platforms-instance-playcount">
% if top_stat['stat_type'] == 'total_plays': % if top_stat['stat_type'] == 'total_plays':
<h3>${top_stat['rows'][0]['total_plays']}</h3> <h3>${top_stat['rows'][0]['total_plays']}</h3>
<p> plays</p> <p> plays</p>
@@ -305,13 +305,13 @@ DOCUMENTATION :: END
<div class="home-platforms-instance-info"> <div class="home-platforms-instance-info">
<div class="home-platforms-instance-name"> <div class="home-platforms-instance-name">
<h4>Most Popular Movie</h4> <h4>Most Popular Movie</h4>
<h5> </div>
<div class="home-platforms-instance-playcount">
<h4>
<a href="info?item_id=${top_stat['rows'][0]['rating_key']}"> <a href="info?item_id=${top_stat['rows'][0]['rating_key']}">
${top_stat['rows'][0]['title']} ${top_stat['rows'][0]['title']}
</a> </a>
</h5> </h4>
</div>
<div class="home-platforms-instance-playcount">
<h3>${top_stat['rows'][0]['users_watched']}</h3> <h3>${top_stat['rows'][0]['users_watched']}</h3>
<p> users</p> <p> users</p>
</div> </div>
@@ -377,7 +377,9 @@ DOCUMENTATION :: END
<div class="home-platforms-instance-info"> <div class="home-platforms-instance-info">
<div class="home-platforms-instance-name"> <div class="home-platforms-instance-name">
<h4>Most Active User</h4> <h4>Most Active User</h4>
<h5> </div>
<div class="home-platforms-instance-playcount">
<h4>
% if top_stat['rows'][0]['user_id']: % if top_stat['rows'][0]['user_id']:
<a href="user?user_id=${top_stat['rows'][0]['user_id']}"> <a href="user?user_id=${top_stat['rows'][0]['user_id']}">
% else: % else:
@@ -385,9 +387,7 @@ DOCUMENTATION :: END
% endif % endif
${top_stat['rows'][0]['friendly_name']} ${top_stat['rows'][0]['friendly_name']}
</a> </a>
</h5> </h4>
</div>
<div class="home-platforms-instance-playcount">
% if top_stat['stat_type'] == 'total_plays': % if top_stat['stat_type'] == 'total_plays':
<h3>${top_stat['rows'][0]['total_plays']}</h3> <h3>${top_stat['rows'][0]['total_plays']}</h3>
<p> plays</p> <p> plays</p>
@@ -473,9 +473,9 @@ DOCUMENTATION :: END
<div class="home-platforms-instance-info"> <div class="home-platforms-instance-info">
<div class="home-platforms-instance-name"> <div class="home-platforms-instance-name">
<h4>Most Active Platform</h4> <h4>Most Active Platform</h4>
<h5>${top_stat['rows'][0]['platform_type']}</h5>
</div> </div>
<div class="home-platforms-instance-playcount"> <div class="home-platforms-instance-playcount">
<h4>${top_stat['rows'][0]['platform_type']}</h4>
% if top_stat['stat_type'] == 'total_plays': % if top_stat['stat_type'] == 'total_plays':
<h3>${top_stat['rows'][0]['total_plays']}</h3> <h3>${top_stat['rows'][0]['total_plays']}</h3>
<p> plays</p> <p> plays</p>
@@ -535,13 +535,13 @@ DOCUMENTATION :: END
<div class="home-platforms-instance-info"> <div class="home-platforms-instance-info">
<div class="home-platforms-instance-name"> <div class="home-platforms-instance-name">
<h4>Last Watched</h4> <h4>Last Watched</h4>
<h5> </div>
<div class="home-platforms-instance-last-user">
<h4>
<a href="info?source=history&item_id=${top_stat['rows'][0]['row_id']}"> <a href="info?source=history&item_id=${top_stat['rows'][0]['row_id']}">
${top_stat['rows'][0]['title']} ${top_stat['rows'][0]['title']}
</a> </a>
</h5> </h4>
</div>
<div class="home-platforms-instance-last-user">
<h5> <h5>
% if top_stat['rows'][0]['user_id']: % if top_stat['rows'][0]['user_id']:
<a href="user?user_id=${top_stat['rows'][0]['user_id']}"> <a href="user?user_id=${top_stat['rows'][0]['user_id']}">

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

@@ -81,13 +81,21 @@ DOCUMENTATION :: END
<div class="summary-content-title-wrapper"> <div class="summary-content-title-wrapper">
<div class="col-md-9"> <div class="col-md-9">
<div class="summary-content-poster hidden-xs hidden-sm"> <div class="summary-content-poster hidden-xs hidden-sm">
<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">
% if data['type'] == 'episode': % 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> <div class="summary-poster-face-episode" style="background-image: url(pms_image_proxy?img=${data['thumb']}&width=500&height=280&fallback=poster);">
% elif data['type'] == 'season': <div class="summary-poster-face-overlay">
<div class="summary-poster-face" style="background-image: url(pms_image_proxy?img=${data['thumb']}&width=300&height=450&fallback=poster);"></div> <span></span>
</div>
</div>
% else: % else:
<div class="summary-poster-face" style="background-image: url(pms_image_proxy?img=${data['thumb']}&width=300&height=450&fallback=poster);"></div> <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 % endif
</a>
</div> </div>
<div class="summary-content-title"> <div class="summary-content-title">
% if data['type'] == 'movie' or data['type'] == 'show': % if data['type'] == 'movie' or data['type'] == 'show':
@@ -144,6 +152,11 @@ DOCUMENTATION :: END
% endif % endif
</div> </div>
</div> </div>
% if data['type'] == 'movie' and data['tagline']:
<div class="summary-content-summary">
<p><strong> ${data['tagline']} </strong></p>
</div>
% endif
<div class="summary-content-summary"> <div class="summary-content-summary">
<p> ${data['summary']} </p> <p> ${data['summary']} </p>
</div> </div>
@@ -258,6 +271,24 @@ DOCUMENTATION :: END
</div> </div>
<div class="modal fade" id="ip-info-modal" tabindex="-1" role="dialog" aria-labelledby="ip-info-modal"> <div class="modal fade" id="ip-info-modal" tabindex="-1" role="dialog" aria-labelledby="ip-info-modal">
</div> </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> </div>
% endif % endif
</div> </div>
@@ -307,19 +338,43 @@ DOCUMENTATION :: END
} }
} }
history_table = $('#history_table').DataTable(history_table_options); 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] }); 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'); $(colvis.button()).appendTo('div.colvis-button-bar');
clearSearchButton('history_table', history_table); clearSearchButton('history_table', history_table);
$('#row-edit-mode').click(function() { $('#row-edit-mode').on('click', function() {
$('#row-edit-mode-alert').fadeIn(200);
if ($(this).hasClass('active')) { if ($(this).hasClass('active')) {
$('.delete-control').each(function() { if (history_to_delete.length > 0) {
$(this).addClass('hidden'); $('#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 { } else {
history_to_delete = [];
$('.delete-control').each(function() { $('.delete-control').each(function() {
$(this).find('button.btn-danger').toggleClass('btn-warning').toggleClass('btn-danger');
$(this).removeClass('hidden'); $(this).removeClass('hidden');
}); });
} }
@@ -381,6 +436,7 @@ DOCUMENTATION :: END
} }
}); });
}); });
$.ajax({ $.ajax({
url: 'get_show_children', url: 'get_show_children',
type: "GET", type: "GET",
@@ -460,9 +516,7 @@ DOCUMENTATION :: END
<script> <script>
$("#airdate").html(moment($("#airdate").text()).format('MMM DD, YYYY')); $("#airdate").html(moment($("#airdate").text()).format('MMM DD, YYYY'));
$("#runtime").html(millisecondsToMinutes($("#runtime").text(), true)); $("#runtime").html(millisecondsToMinutes($("#runtime").text(), true));
</script>
% endif
<script>
$('div.art-face').animate({ opacity: 0.2 }, { duration: 1000 }); $('div.art-face').animate({ opacity: 0.2 }, { duration: 1000 });
</script> </script>
% endif
</%def> </%def>

View File

@@ -219,6 +219,10 @@ function getPlatformImagePath(platformName) {
return 'interfaces/default/images/platforms/playstation.png'; return 'interfaces/default/images/platforms/playstation.png';
} else if (platformName.indexOf("Mystery 5") > -1) { } else if (platformName.indexOf("Mystery 5") > -1) {
return 'interfaces/default/images/platforms/xbox.png'; return 'interfaces/default/images/platforms/xbox.png';
} 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 { } else {
return 'interfaces/default/images/platforms/default.png'; return 'interfaces/default/images/platforms/default.png';
} }

View File

@@ -38,21 +38,21 @@ DOCUMENTATION :: END
<div class="home-platforms-instance-info"> <div class="home-platforms-instance-info">
<div class="home-platforms-instance-name"> <div class="home-platforms-instance-name">
<h4>${library['rows']['title']}</h4> <h4>${library['rows']['title']}</h4>
<h5>${library['rows']['count_type']}</h5>
</div> </div>
<div class="home-platforms-instance-playcount"> <div class="home-platforms-instance-playcount">
<h5>${library['rows']['count_type']}</h5>
<h3>${library['rows']['count']}</h3> <h3>${library['rows']['count']}</h3>
<p> items</p> <p> items</p>
</div> </div>
% if library['type'] == 'show': % if library['type'] == 'show':
<div class="home-platforms-instance-name2"> <div class="home-platforms-instance-playcount" style="padding-left: 10px;">
<h5>${library['rows']['episode_count_type']}</h5> <h5>${library['rows']['episode_count_type']}</h5>
<h3>${library['rows']['episode_count']}</h3> <h3>${library['rows']['episode_count']}</h3>
<p> items</p> <p> items</p>
</div> </div>
% endif % endif
% if library['type'] == 'artist': % if library['type'] == 'artist':
<div class="home-platforms-instance-name2"> <div class="home-platforms-instance-playcount" style="padding-left: 10px;">
<h5>${library['rows']['album_count_type']}</h5> <h5>${library['rows']['album_count_type']}</h5>
<h3>${library['rows']['album_count']}</h3> <h3>${library['rows']['album_count']}</h3>
<p> items</p> <p> items</p>

View File

@@ -321,7 +321,7 @@ available_notification_agents = notifiers.available_notification_agents()
<div class="checkbox"> <div class="checkbox">
<label> <label>
<input type="checkbox" id="pms_use_bif" name="pms_use_bif" value="1" ${config['pms_use_bif']}> Use BIF thumbs <input type="checkbox" id="pms_use_bif" name="pms_use_bif" value="1" ${config['pms_use_bif']}> Use video preview thumbnails (BIF)
</label> </label>
<p class="help-block">If you have media indexing enabled on your server, use these on the activity pane.</p> <p class="help-block">If you have media indexing enabled on your server, use these on the activity pane.</p>
</div> </div>

View File

@@ -16,7 +16,7 @@
<button class="btn btn-danger btn-edit" data-toggle="button" aria-pressed="false" autocomplete="off" id="row-edit-mode"> <button class="btn btn-danger btn-edit" data-toggle="button" aria-pressed="false" autocomplete="off" id="row-edit-mode">
<i class="fa fa-pencil"></i> Edit mode <i class="fa fa-pencil"></i> Edit mode
</button>&nbsp </button>&nbsp
<div class="alert alert-danger alert-edit" role="alert" id="row-edit-mode-alert"><i class="fa fa-exclamation-triangle"></i>&nbspSelect rows to delete. Data is deleted upon exiting delete mode.</div> <div class="alert alert-danger alert-edit" role="alert" id="row-edit-mode-alert"><i class="fa fa-exclamation-triangle"></i>&nbspSelect users to purge. Data is purged upon exiting edit mode.</div>
</div> </div>
</div> </div>
<div class='table-card-back'> <div class='table-card-back'>
@@ -119,6 +119,13 @@
$(this).addClass('hidden'); $(this).addClass('hidden');
$('#row-edit-mode-alert').fadeOut(200); $('#row-edit-mode-alert').fadeOut(200);
}); });
$('.edit-user-control > .edit-user-name').each(function () {
a = $(this).children('a');
input = $(this).children('input');
a.text(input.val());
a.removeClass('hidden');
input.addClass('hidden');
});
} else { } else {
users_to_purge = []; users_to_purge = [];
@@ -126,6 +133,10 @@
$(this).find('button.btn-danger').toggleClass('btn-warning').toggleClass('btn-danger'); $(this).find('button.btn-danger').toggleClass('btn-warning').toggleClass('btn-danger');
$(this).removeClass('hidden'); $(this).removeClass('hidden');
}); });
$('.edit-user-control > .edit-user-name').each(function () {
$(this).children('a').addClass('hidden');
$(this).children('input').removeClass('hidden');
});
} }
}); });
}); });

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 # PlexPy is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@@ -377,7 +377,7 @@ def dbcheck():
'title TEXT, parent_title TEXT, grandparent_title TEXT, full_title TEXT, media_index INTEGER, ' 'title TEXT, parent_title TEXT, grandparent_title TEXT, full_title TEXT, media_index INTEGER, '
'parent_media_index INTEGER, thumb TEXT, parent_thumb TEXT, grandparent_thumb TEXT, art TEXT, media_type TEXT, ' 'parent_media_index INTEGER, thumb TEXT, parent_thumb TEXT, grandparent_thumb TEXT, art TEXT, media_type TEXT, '
'year INTEGER, originally_available_at TEXT, added_at INTEGER, updated_at INTEGER, last_viewed_at INTEGER, ' 'year INTEGER, originally_available_at TEXT, added_at INTEGER, updated_at INTEGER, last_viewed_at INTEGER, '
'content_rating TEXT, summary TEXT, rating TEXT, duration INTEGER DEFAULT 0, guid TEXT, ' 'content_rating TEXT, summary TEXT, tagline TEXT, rating TEXT, duration INTEGER DEFAULT 0, guid TEXT, '
'directors TEXT, writers TEXT, actors TEXT, genres TEXT, studio TEXT)' 'directors TEXT, writers TEXT, actors TEXT, genres TEXT, studio TEXT)'
'' ''
) )
@@ -517,15 +517,24 @@ def dbcheck():
'ALTER TABLE sessions ADD COLUMN transcode_height INTEGER' 'ALTER TABLE sessions ADD COLUMN transcode_height INTEGER'
) )
# Upgrade sessions table from earlier versions # Upgrade session_history_metadata table from earlier versions
try: try:
c_db.execute('SELECT full_title from session_history_metadata') c_db.execute('SELECT full_title from session_history_metadata')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table sessions.") logger.debug(u"Altering database. Updating database table session_history_metadata.")
c_db.execute( c_db.execute(
'ALTER TABLE session_history_metadata ADD COLUMN full_title TEXT' 'ALTER TABLE session_history_metadata ADD COLUMN full_title TEXT'
) )
# Upgrade session_history_metadata table from earlier versions
try:
c_db.execute('SELECT tagline from session_history_metadata')
except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table session_history_metadata.")
c_db.execute(
'ALTER TABLE session_history_metadata ADD COLUMN tagline TEXT'
)
# notify_log table :: This is a table which logs notifications sent # notify_log table :: This is a table which logs notifications sent
c_db.execute( c_db.execute(
'CREATE TABLE IF NOT EXISTS notify_log (id INTEGER PRIMARY KEY AUTOINCREMENT, ' 'CREATE TABLE IF NOT EXISTS notify_log (id INTEGER PRIMARY KEY AUTOINCREMENT, '

View File

@@ -578,8 +578,8 @@ class DataFactory(object):
if row_id: if row_id:
query = 'SELECT rating_key, parent_rating_key, grandparent_rating_key, title, parent_title, grandparent_title, ' \ query = 'SELECT rating_key, parent_rating_key, grandparent_rating_key, title, parent_title, grandparent_title, ' \
'full_title, media_index, parent_media_index, thumb, parent_thumb, grandparent_thumb, art, media_type, ' \ 'full_title, media_index, parent_media_index, thumb, parent_thumb, grandparent_thumb, art, media_type, ' \
'year, originally_available_at, added_at, updated_at, last_viewed_at, content_rating, summary, rating, ' \ 'year, originally_available_at, added_at, updated_at, last_viewed_at, content_rating, summary, tagline, ' \
'duration, guid, directors, writers, actors, genres, studio ' \ 'rating, duration, guid, directors, writers, actors, genres, studio ' \
'FROM session_history_metadata ' \ 'FROM session_history_metadata ' \
'WHERE id = ?' 'WHERE id = ?'
result = monitor_db.select(query=query, args=[row_id]) result = monitor_db.select(query=query, args=[row_id])
@@ -605,6 +605,7 @@ class DataFactory(object):
'title': item['title'], 'title': item['title'],
'content_rating': item['content_rating'], 'content_rating': item['content_rating'],
'summary': item['summary'], 'summary': item['summary'],
'tagline': item['tagline'],
'rating': item['rating'], 'rating': item['rating'],
'duration': item['duration'], 'duration': item['duration'],
'year': item['year'], 'year': item['year'],

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 # PlexPy is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@@ -343,17 +343,17 @@ class MonitorProcessing(object):
'grandparent_rating_key, title, parent_title, grandparent_title, full_title, media_index, ' \ 'grandparent_rating_key, title, parent_title, grandparent_title, full_title, media_index, ' \
'parent_media_index, thumb, parent_thumb, grandparent_thumb, art, media_type, year, ' \ 'parent_media_index, thumb, parent_thumb, grandparent_thumb, art, media_type, year, ' \
'originally_available_at, added_at, updated_at, last_viewed_at, content_rating, summary, ' \ 'originally_available_at, added_at, updated_at, last_viewed_at, content_rating, summary, ' \
'rating, duration, guid, directors, writers, actors, genres, studio) VALUES ' \ 'tagline, rating, duration, guid, directors, writers, actors, genres, studio) VALUES ' \
'(last_insert_rowid(), ' \ '(last_insert_rowid(), ' \
'?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)' '?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'
args = [session['rating_key'], session['parent_rating_key'], session['grandparent_rating_key'], args = [session['rating_key'], session['parent_rating_key'], session['grandparent_rating_key'],
session['title'], session['parent_title'], session['grandparent_title'], full_title, session['title'], session['parent_title'], session['grandparent_title'], full_title,
metadata['index'], metadata['parent_index'], metadata['thumb'], metadata['parent_thumb'], metadata['index'], metadata['parent_index'], metadata['thumb'], metadata['parent_thumb'],
metadata['grandparent_thumb'], metadata['art'], session['media_type'], metadata['year'], metadata['grandparent_thumb'], metadata['art'], session['media_type'], metadata['year'],
metadata['originally_available_at'], metadata['added_at'], metadata['updated_at'], metadata['originally_available_at'], metadata['added_at'], metadata['updated_at'],
metadata['last_viewed_at'], metadata['content_rating'], metadata['summary'], metadata['rating'], metadata['last_viewed_at'], metadata['content_rating'], metadata['summary'], metadata['tagline'],
metadata['duration'], metadata['guid'], directors, writers, actors, genres, metadata['studio']] metadata['rating'], metadata['duration'], metadata['guid'], directors, writers, actors, genres, metadata['studio']]
# logger.debug(u"PlexPy Monitor :: Writing session_history_metadata transaction...") # logger.debug(u"PlexPy Monitor :: Writing session_history_metadata transaction...")
self.db.action(query=query, args=args) self.db.action(query=query, args=args)

View File

@@ -349,14 +349,14 @@ def build_notify_text(session, state):
if on_start_subject and on_start_body: if on_start_subject and on_start_body:
try: try:
subject_text = on_start_subject.format(**available_params) subject_text = unicode(on_start_subject).format(**available_params)
except LookupError, e: except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e) logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
except: except:
logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.") logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
try: try:
body_text = on_start_body.format(**available_params) body_text = unicode(on_start_body).format(**available_params)
except LookupError, e: except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e) logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
except: except:
@@ -373,14 +373,14 @@ def build_notify_text(session, state):
if on_stop_subject and on_stop_body: if on_stop_subject and on_stop_body:
try: try:
subject_text = on_stop_subject.format(**available_params) subject_text = unicode(on_stop_subject).format(**available_params)
except LookupError, e: except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e) logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
except: except:
logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.") logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
try: try:
body_text = on_stop_body.format(**available_params) body_text = unicode(on_stop_body).format(**available_params)
except LookupError, e: except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e) logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
except: except:
@@ -397,14 +397,14 @@ def build_notify_text(session, state):
if on_pause_subject and on_pause_body: if on_pause_subject and on_pause_body:
try: try:
subject_text = on_pause_subject.format(**available_params) subject_text = unicode(on_pause_subject).format(**available_params)
except LookupError, e: except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e) logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
except: except:
logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.") logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
try: try:
body_text = on_pause_body.format(**available_params) body_text = unicode(on_pause_body).format(**available_params)
except LookupError, e: except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e) logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
except: except:
@@ -421,14 +421,14 @@ def build_notify_text(session, state):
if on_resume_subject and on_resume_body: if on_resume_subject and on_resume_body:
try: try:
subject_text = on_resume_subject.format(**available_params) subject_text = unicode(on_resume_subject).format(**available_params)
except LookupError, e: except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e) logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
except: except:
logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.") logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
try: try:
body_text = on_resume_body.format(**available_params) body_text = unicode(on_resume_body).format(**available_params)
except LookupError, e: except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e) logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
except: except:
@@ -445,14 +445,14 @@ def build_notify_text(session, state):
if on_buffer_subject and on_buffer_body: if on_buffer_subject and on_buffer_body:
try: try:
subject_text = on_buffer_subject.format(**available_params) subject_text = unicode(on_buffer_subject).format(**available_params)
except LookupError, e: except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e) logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
except: except:
logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.") logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
try: try:
body_text = on_buffer_body.format(**available_params) body_text = unicode(on_buffer_body).format(**available_params)
except LookupError, e: except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e) logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
except: except:
@@ -469,14 +469,14 @@ def build_notify_text(session, state):
if on_watched_subject and on_watched_body: if on_watched_subject and on_watched_body:
try: try:
subject_text = on_watched_subject.format(**available_params) subject_text = unicode(on_watched_subject).format(**available_params)
except LookupError, e: except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e) logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
except: except:
logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.") logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
try: try:
body_text = on_watched_body.format(**available_params) body_text = unicode(on_watched_body).format(**available_params)
except LookupError, e: except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e) logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
except: except:

View File

@@ -55,6 +55,7 @@ def extract_plexwatch_xml(xml=None):
parent_title = helpers.get_xml_attr(a, 'parentTitle') parent_title = helpers.get_xml_attr(a, 'parentTitle')
studio = helpers.get_xml_attr(a, 'studio') studio = helpers.get_xml_attr(a, 'studio')
title = helpers.get_xml_attr(a, 'title') title = helpers.get_xml_attr(a, 'title')
tagline = helpers.get_xml_attr(a, 'tagline')
directors = [] directors = []
if a.getElementsByTagName('Director'): if a.getElementsByTagName('Director'):
@@ -153,6 +154,7 @@ def extract_plexwatch_xml(xml=None):
'grandparent_title': grandparent_title, 'grandparent_title': grandparent_title,
'parent_title': parent_title, 'parent_title': parent_title,
'title': title, 'title': title,
'tagline': tagline,
'guid': guid, 'guid': guid,
'media_index': media_index, 'media_index': media_index,
'originally_available_at': originally_available_at, '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'], 'last_viewed_at': extracted_xml['last_viewed_at'],
'content_rating': row['content_rating'], 'content_rating': row['content_rating'],
'summary': row['summary'], 'summary': row['summary'],
'tagline': extracted_xml['tagline'],
'rating': extracted_xml['rating'], 'rating': extracted_xml['rating'],
'duration': extracted_xml['duration'], 'duration': extracted_xml['duration'],
'guid': extracted_xml['guid'], 'guid': extracted_xml['guid'],

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 # PlexPy is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@@ -362,6 +362,7 @@ class PmsConnect(object):
'title': helpers.get_xml_attr(metadata_main, 'title'), 'title': helpers.get_xml_attr(metadata_main, 'title'),
'content_rating': helpers.get_xml_attr(metadata_main, 'contentRating'), 'content_rating': helpers.get_xml_attr(metadata_main, 'contentRating'),
'summary': helpers.get_xml_attr(metadata_main, 'summary'), 'summary': helpers.get_xml_attr(metadata_main, 'summary'),
'tagline': helpers.get_xml_attr(metadata_main, 'tagline'),
'rating': helpers.get_xml_attr(metadata_main, 'rating'), 'rating': helpers.get_xml_attr(metadata_main, 'rating'),
'duration': helpers.get_xml_attr(metadata_main, 'duration'), 'duration': helpers.get_xml_attr(metadata_main, 'duration'),
'year': helpers.get_xml_attr(metadata_main, 'year'), 'year': helpers.get_xml_attr(metadata_main, 'year'),
@@ -383,6 +384,8 @@ class PmsConnect(object):
elif metadata_type == 'episode': elif metadata_type == 'episode':
metadata = {'type': metadata_type, metadata = {'type': metadata_type,
'rating_key': helpers.get_xml_attr(metadata_main, 'ratingKey'), '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'), 'grandparent_title': helpers.get_xml_attr(metadata_main, 'grandparentTitle'),
'parent_index': helpers.get_xml_attr(metadata_main, 'parentIndex'), 'parent_index': helpers.get_xml_attr(metadata_main, 'parentIndex'),
'parent_title': helpers.get_xml_attr(metadata_main, 'parentTitle'), 'parent_title': helpers.get_xml_attr(metadata_main, 'parentTitle'),
@@ -391,6 +394,7 @@ class PmsConnect(object):
'title': helpers.get_xml_attr(metadata_main, 'title'), 'title': helpers.get_xml_attr(metadata_main, 'title'),
'content_rating': helpers.get_xml_attr(metadata_main, 'contentRating'), 'content_rating': helpers.get_xml_attr(metadata_main, 'contentRating'),
'summary': helpers.get_xml_attr(metadata_main, 'summary'), 'summary': helpers.get_xml_attr(metadata_main, 'summary'),
'tagline': helpers.get_xml_attr(metadata_main, 'tagline'),
'rating': helpers.get_xml_attr(metadata_main, 'rating'), 'rating': helpers.get_xml_attr(metadata_main, 'rating'),
'duration': helpers.get_xml_attr(metadata_main, 'duration'), 'duration': helpers.get_xml_attr(metadata_main, 'duration'),
'year': helpers.get_xml_attr(metadata_main, 'year'), 'year': helpers.get_xml_attr(metadata_main, 'year'),
@@ -420,6 +424,7 @@ class PmsConnect(object):
'title': helpers.get_xml_attr(metadata_main, 'title'), 'title': helpers.get_xml_attr(metadata_main, 'title'),
'content_rating': helpers.get_xml_attr(metadata_main, 'contentRating'), 'content_rating': helpers.get_xml_attr(metadata_main, 'contentRating'),
'summary': helpers.get_xml_attr(metadata_main, 'summary'), 'summary': helpers.get_xml_attr(metadata_main, 'summary'),
'tagline': helpers.get_xml_attr(metadata_main, 'tagline'),
'rating': helpers.get_xml_attr(metadata_main, 'rating'), 'rating': helpers.get_xml_attr(metadata_main, 'rating'),
'duration': helpers.get_xml_attr(metadata_main, 'duration'), 'duration': helpers.get_xml_attr(metadata_main, 'duration'),
'year': helpers.get_xml_attr(metadata_main, 'year'), 'year': helpers.get_xml_attr(metadata_main, 'year'),
@@ -443,6 +448,7 @@ class PmsConnect(object):
show_details = self.get_metadata_details(parent_rating_key) show_details = self.get_metadata_details(parent_rating_key)
metadata = {'type': metadata_type, metadata = {'type': metadata_type,
'rating_key': helpers.get_xml_attr(metadata_main, 'ratingKey'), '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'), 'grandparent_title': helpers.get_xml_attr(metadata_main, 'grandparentTitle'),
'parent_index': helpers.get_xml_attr(metadata_main, 'parentIndex'), 'parent_index': helpers.get_xml_attr(metadata_main, 'parentIndex'),
'parent_title': helpers.get_xml_attr(metadata_main, 'parentTitle'), 'parent_title': helpers.get_xml_attr(metadata_main, 'parentTitle'),
@@ -451,6 +457,7 @@ class PmsConnect(object):
'title': helpers.get_xml_attr(metadata_main, 'title'), 'title': helpers.get_xml_attr(metadata_main, 'title'),
'content_rating': helpers.get_xml_attr(metadata_main, 'contentRating'), 'content_rating': helpers.get_xml_attr(metadata_main, 'contentRating'),
'summary': show_details['metadata']['summary'], 'summary': show_details['metadata']['summary'],
'tagline': helpers.get_xml_attr(metadata_main, 'tagline'),
'rating': helpers.get_xml_attr(metadata_main, 'rating'), 'rating': helpers.get_xml_attr(metadata_main, 'rating'),
'duration': show_details['metadata']['duration'], 'duration': show_details['metadata']['duration'],
'year': helpers.get_xml_attr(metadata_main, 'year'), 'year': helpers.get_xml_attr(metadata_main, 'year'),
@@ -480,6 +487,7 @@ class PmsConnect(object):
'title': helpers.get_xml_attr(metadata_main, 'title'), 'title': helpers.get_xml_attr(metadata_main, 'title'),
'content_rating': helpers.get_xml_attr(metadata_main, 'contentRating'), 'content_rating': helpers.get_xml_attr(metadata_main, 'contentRating'),
'summary': helpers.get_xml_attr(metadata_main, 'summary'), 'summary': helpers.get_xml_attr(metadata_main, 'summary'),
'tagline': helpers.get_xml_attr(metadata_main, 'tagline'),
'rating': helpers.get_xml_attr(metadata_main, 'rating'), 'rating': helpers.get_xml_attr(metadata_main, 'rating'),
'duration': helpers.get_xml_attr(metadata_main, 'duration'), 'duration': helpers.get_xml_attr(metadata_main, 'duration'),
'year': helpers.get_xml_attr(metadata_main, 'year'), 'year': helpers.get_xml_attr(metadata_main, 'year'),
@@ -570,6 +578,9 @@ class PmsConnect(object):
if session.getElementsByTagName('TranscodeSession'): if session.getElementsByTagName('TranscodeSession'):
transcode_session = session.getElementsByTagName('TranscodeSession')[0] 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')
audio_decision = helpers.get_xml_attr(transcode_session, 'audioDecision') audio_decision = helpers.get_xml_attr(transcode_session, 'audioDecision')
transcode_audio_channels = helpers.get_xml_attr(transcode_session, 'audioChannels') transcode_audio_channels = helpers.get_xml_attr(transcode_session, 'audioChannels')
transcode_audio_codec = helpers.get_xml_attr(transcode_session, 'audioCodec') transcode_audio_codec = helpers.get_xml_attr(transcode_session, 'audioCodec')
@@ -577,6 +588,9 @@ class PmsConnect(object):
transcode_protocol = helpers.get_xml_attr(transcode_session, 'protocol') transcode_protocol = helpers.get_xml_attr(transcode_session, 'protocol')
duration = helpers.get_xml_attr(transcode_session, 'duration') duration = helpers.get_xml_attr(transcode_session, 'duration')
else: else:
throttled = '0'
transcode_progress = '0'
transcode_speed = ''
transcode_audio_channels = '' transcode_audio_channels = ''
transcode_audio_codec = '' transcode_audio_codec = ''
transcode_container = '' transcode_container = ''
@@ -612,6 +626,9 @@ class PmsConnect(object):
'rating_key': helpers.get_xml_attr(session, 'ratingKey'), 'rating_key': helpers.get_xml_attr(session, 'ratingKey'),
'parent_rating_key': helpers.get_xml_attr(session, 'parentRatingKey'), 'parent_rating_key': helpers.get_xml_attr(session, 'parentRatingKey'),
'grandparent_rating_key': helpers.get_xml_attr(session, 'grandparentRatingKey'), '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_decision, 'audio_decision': audio_decision,
'audio_channels': audio_channels, 'audio_channels': audio_channels,
'audio_codec': audio_codec, 'audio_codec': audio_codec,
@@ -656,6 +673,9 @@ class PmsConnect(object):
if session.getElementsByTagName('TranscodeSession'): if session.getElementsByTagName('TranscodeSession'):
transcode_session = session.getElementsByTagName('TranscodeSession')[0] 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')
audio_decision = helpers.get_xml_attr(transcode_session, 'audioDecision') audio_decision = helpers.get_xml_attr(transcode_session, 'audioDecision')
transcode_audio_channels = helpers.get_xml_attr(transcode_session, 'audioChannels') transcode_audio_channels = helpers.get_xml_attr(transcode_session, 'audioChannels')
transcode_audio_codec = helpers.get_xml_attr(transcode_session, 'audioCodec') transcode_audio_codec = helpers.get_xml_attr(transcode_session, 'audioCodec')
@@ -666,6 +686,9 @@ class PmsConnect(object):
transcode_container = helpers.get_xml_attr(transcode_session, 'container') transcode_container = helpers.get_xml_attr(transcode_session, 'container')
transcode_protocol = helpers.get_xml_attr(transcode_session, 'protocol') transcode_protocol = helpers.get_xml_attr(transcode_session, 'protocol')
else: else:
throttled = '0'
transcode_progress = '0'
transcode_speed = ''
transcode_audio_channels = '' transcode_audio_channels = ''
transcode_audio_codec = '' transcode_audio_codec = ''
transcode_video_codec = '' transcode_video_codec = ''
@@ -723,6 +746,9 @@ class PmsConnect(object):
'rating_key': helpers.get_xml_attr(session, 'ratingKey'), 'rating_key': helpers.get_xml_attr(session, 'ratingKey'),
'parent_rating_key': helpers.get_xml_attr(session, 'parentRatingKey'), 'parent_rating_key': helpers.get_xml_attr(session, 'parentRatingKey'),
'grandparent_rating_key': helpers.get_xml_attr(session, 'grandparentRatingKey'), '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_decision, 'audio_decision': audio_decision,
'audio_channels': audio_channels, 'audio_channels': audio_channels,
'audio_codec': audio_codec, 'audio_codec': audio_codec,
@@ -776,6 +802,9 @@ class PmsConnect(object):
'rating_key': helpers.get_xml_attr(session, 'ratingKey'), 'rating_key': helpers.get_xml_attr(session, 'ratingKey'),
'parent_rating_key': helpers.get_xml_attr(session, 'parentRatingKey'), 'parent_rating_key': helpers.get_xml_attr(session, 'parentRatingKey'),
'grandparent_rating_key': helpers.get_xml_attr(session, 'grandparentRatingKey'), '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_decision, 'audio_decision': audio_decision,
'audio_channels': audio_channels, 'audio_channels': audio_channels,
'audio_codec': audio_codec, 'audio_codec': audio_codec,
@@ -829,6 +858,9 @@ class PmsConnect(object):
'rating_key': helpers.get_xml_attr(session, 'ratingKey'), 'rating_key': helpers.get_xml_attr(session, 'ratingKey'),
'parent_rating_key': helpers.get_xml_attr(session, 'parentRatingKey'), 'parent_rating_key': helpers.get_xml_attr(session, 'parentRatingKey'),
'grandparent_rating_key': helpers.get_xml_attr(session, 'grandparentRatingKey'), '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_decision, 'audio_decision': audio_decision,
'audio_channels': audio_channels, 'audio_channels': audio_channels,
'audio_codec': audio_codec, 'audio_codec': audio_codec,

View File

@@ -1,2 +1,2 @@
PLEXPY_VERSION = "master" PLEXPY_VERSION = "master"
PLEXPY_RELEASE_VERSION = "1.1.6" PLEXPY_RELEASE_VERSION = "1.1.8"

View File

@@ -762,6 +762,10 @@ class WebInterface(object):
def info(self, item_id=None, source=None, **kwargs): def info(self, item_id=None, source=None, **kwargs):
metadata = None metadata = None
config = {
"pms_identifier": plexpy.CONFIG.PMS_IDENTIFIER
}
if source == 'history': if source == 'history':
data_factory = datafactory.DataFactory() data_factory = datafactory.DataFactory()
metadata = data_factory.get_metadata_details(row_id=item_id) metadata = data_factory.get_metadata_details(row_id=item_id)
@@ -772,7 +776,7 @@ class WebInterface(object):
metadata = result['metadata'] metadata = result['metadata']
if 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: else:
logger.warn('Unable to retrieve data.') logger.warn('Unable to retrieve data.')
return serve_template(templatename="info.html", data=None, title="Info") return serve_template(templatename="info.html", data=None, title="Info")