Merge pull request #708 from JackDandy/feature/AddFanArt

Add fanart to Episodes View, Display Show, and Edit Show page.
This commit is contained in:
JackDandy 2016-12-16 22:39:54 +00:00 committed by GitHub
commit d372bd5453
80 changed files with 6403 additions and 2403 deletions

View file

@ -201,6 +201,56 @@
* Change sab API request to prevent naming mismatch * Change sab API request to prevent naming mismatch
* Change update rTorrent systems * Change update rTorrent systems
* Change logger to properly cleanup used resources * Change logger to properly cleanup used resources
* Add fanart to Episodes View, Display Show, and Edit Show page
* Add path used for fanart images <Cache Dir>/images/fanart (<Cache Dir> value on Help page)
* Add populate images when the daily show updater is run with default maximum 3 images per show
* Change force full update in a show will replace existing images with new
* Add "Maximum fanart image files per show to cache" to config General/Interface
* Add fanart livepanel to lower right of Episodes View and Display Show page
* Add highlight panel red on Episodes view until button is clicked a few times
* Add flick through multiple background images on Episodes View and Display Show page
* Add persistent move poster image to right hand side or hide on Display Show page (multi-click the eye)
* Add persistent translucency of background images on Episodes View and Display Show page
* Add persistent fanart rating to avoid art completely, random display, random from a group, or display fave always
* Add persistent views of the show detail on Display Show page
* Add persistent views on Episodes View
* Add persistent button to collapse and expand card images on Episode View/Layout daybyday
* Add non persistent "Open gear" and "Backart only" image views to Episodes View and Display Show page
* Add "smart" selection of fanart image to display on Episode view
* Change insert [!] and change text shade of ended shows in drop down show list on Display Show page
* Change button graphic for next and previous show of show list on Display Show page
* Add logic to hide some livepanel buttons until artwork becomes available or in other circumstances
* Add "(Ended)" where appropriate to show title on Display Show page
* Change use tense for label "Airs" or "Aired" depending on if show ended
* Change display "No files" instead of "0 files" and "Upgrade once" instead of "End upgrade on first match"
* Add persistent button to newest season to "Show all" episodes
* Add persistent button to all shown seasons to "Hide most" episodes
* Add button to older seasons to toggle "Show Season n" or "Show Specials" with "Hide..." episodes
* Add season level status counts next to each season header on display show page
* Add sorting to season table headers on display show page
* Add filename and size to quality badge on display show page, removed its redundant "downloaded" text
* Remove redundant "Add show" buttons
* Change combine the NFO and TBN columns into a single Meta column
* Change reduce screen estate used by episode numbers columns
* Change improve clarity of text on Add Show page
* Change rename Edit show/"Post-Processing" tab to "Other"
* Add "Reset fanart ratings" to show Edit/Other tab
* Add fanart keys guide to show Edit/Other tab
* Change add placeholder tip to "Alternative release name(s)" on show Edit
* Change add placeholder tip to search box on shows Search
* Change hide Anime tips on show Edit when selecting its mutually exclusive options
* Change label "End upgrade on first match" to "Upgrade once" on show Edit
* Change improve performance rendering displayShow
* Add total episodes to start of show description (excludes specials if those are hidden)
* Add "Add show" actions i.e. "Search", "Trakt cards", "IMDb cards", and "Anime" to Shows menu
* Add "Import (existing)" action to Tools menu
* Change SD quality from red to dark green, 2160p UHD 4K is red
* Change relocate the functions of Logs & Errors to the right side Tools menu -> View Log File
* Add warning indicator to the Tools menu in different colour depending on error count (green through red)
* Change View Log error item output from reversed to natural order
* Change View Log File add a typeface and some colour to improve readability
* Change View Log File/Errors only display "Clear Errors" button when there are errors to clear
* Change improve performance of View Log File
[develop changelog] [develop changelog]
* Change send nzb data to NZBGet for Anizb instead of url * Change send nzb data to NZBGet for Anizb instead of url
@ -371,7 +421,7 @@
* Fix post processing season pack folders * Fix post processing season pack folders
* Fix saving torrent provider option "Seed until ratio" after recent refactor * Fix saving torrent provider option "Seed until ratio" after recent refactor
* Change white text in light theme on Manage / Episode Status Management page to black for better readability * Change white text in light theme on Manage / Episode Status Management page to black for better readability
* Change displayShow page episode colours when a minimum quality is met with "End upgrade on first match" * Change displayShow page episode colours when a minimum quality is met with "Upgrade once"
* Add seed time per provider for torrent clients that support seed time per torrent, i.e. currently only uTorrent * Add seed time per provider for torrent clients that support seed time per torrent, i.e. currently only uTorrent
* Remove seed time display for Transmission in config/Torrent Search page because the torrent client doesn't support it * Remove seed time display for Transmission in config/Torrent Search page because the torrent client doesn't support it
* Add PreToMe torrent provider * Add PreToMe torrent provider
@ -559,7 +609,7 @@
* Change Trakt url to fix baseline uses (e.g. add from trending) * Change Trakt url to fix baseline uses (e.g. add from trending)
* Fix edit on show page for shows that have anime enabled in mass edit * Fix edit on show page for shows that have anime enabled in mass edit
* Fix issue parsing items in ToktoToshokan provider * Fix issue parsing items in ToktoToshokan provider
* Change to only show option "End upgrade on first match" on edit show page if quality custom is selected * Change to only show option "Upgrade once" on edit show page if quality custom is selected
* Change label "Show is grouped in" in edit show page to "Show is in group" and move the section higher * Change label "Show is grouped in" in edit show page to "Show is in group" and move the section higher
* Fix post processing of anime with version tags * Fix post processing of anime with version tags
* Change accept SD titles that contain audio quality * Change accept SD titles that contain audio quality

View file

@ -12,6 +12,7 @@ Libs with customisations...
/lib/pynma/pynma.py /lib/pynma/pynma.py
/lib/requests/packages/urllib3/connectionpool.py /lib/requests/packages/urllib3/connectionpool.py
/lib/requests/packages/urllib3/util/ssl_.py /lib/requests/packages/urllib3/util/ssl_.py
/lib/tmdb_api/tmdb_api.py
/lib/tornado /lib/tornado
/lib/tvdb/tvdb_api.py /lib/tvdb_api/tvdb_api.py
/lib/tzlocal/unix.py /lib/tzlocal/unix.py

View file

@ -1,6 +1,24 @@
/* ======================================================================= /* =======================================================================
inc_top.tmpl inc_top.tmpl
========================================================================== */ ========================================================================== */
.navbar-default .navbar-nav .logger.errors.n,
pre .prelight{
color:#c3ed9b
}
.navbar-default .navbar-nav .logger.errors.nn,
pre .prelight2{
color:#f6ff41
}
.navbar-default .navbar-nav .logger.errors.nnn,
pre .prelight-num{
color:#ffba57
}
.navbar-default .navbar-nav .logger.errors.nnnn{
color:#ff6d5e
}
[class^="icon-"], [class^="icon-"],
[class*=" icon-"]{ [class*=" icon-"]{
@ -41,21 +59,21 @@ inc_top.tmpl
.ui-widget-content{ .ui-widget-content{
background:#606060; background:#606060;
border:1px solid #111; border:1px solid #111;
color:#fff color:#ddd
} }
.ui-widget-content a{ .ui-widget-content a{
color:#2D8FBF color:#2d8fbf
} }
.ui-widget-content a:hover{ .ui-widget-content a:hover{
color:#09A2FF color:#09a2ff
} }
.ui-widget-header{ .ui-widget-header{
background:#3d3d3d; background:#3d3d3d;
border:1px solid #111; border:1px solid #111;
color:#fff color:#ddd
} }
.ui-state-default, .ui-state-default,
@ -103,7 +121,7 @@ inc_top.tmpl
} }
.ui-state-default .ui-icon{ .ui-state-default .ui-icon{
background-image:url('../css/lib/images/ui-icons_09a2ff_256x240.png') background-image:url("../css/lib/images/ui-icons_09a2ff_256x240.png")
} }
.ui-state-hover .ui-icon, .ui-state-hover .ui-icon,
@ -133,12 +151,12 @@ inc_top.tmpl
} }
.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited{ .ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited{
color:#140F06; color:#140f06;
text-decoration:none text-decoration:none
} }
.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited{ .ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited{
color:#fff; color:#ddd;
text-decoration:none text-decoration:none
} }
@ -180,13 +198,6 @@ inc_top.tmpl
border-top-right-radius:5px border-top-right-radius:5px
} }
#SubMenu{
padding-right:20px;
clear:both;
font-size:12px;
float:right
}
.upgrade-notification{ .upgrade-notification{
width:600px; width:600px;
text-align:center; text-align:center;
@ -201,7 +212,7 @@ inc_bottom.tmpl
========================================================================== */ ========================================================================== */
.footerhighlight{ .footerhighlight{
color:#09A2FF color:#09a2ff
} }
/* ======================================================================= /* =======================================================================
@ -219,7 +230,7 @@ home.tmpl
.ui-font, .ui-font,
a.ui-font{ a.ui-font{
text-shadow:0 0 0.1em #000; text-shadow:0 0 0.1em #000;
color:#fff color:#ddd
} }
#show-list .show-card{ #show-list .show-card{
@ -265,14 +276,14 @@ a.ui-font{
} }
td.tvShow a{ td.tvShow a{
color:#fff; color:#ddd;
text-decoration:none text-decoration:none
} }
td.tvShow a:hover span, td.tvShow a:hover span,
td.tvShow a:hover{ td.tvShow a:hover{
cursor:pointer; cursor:pointer;
color:#09A2FF color:#09a2ff
} }
/* ======================================================================= /* =======================================================================
@ -302,9 +313,8 @@ home_newShow.tmpl
} }
#addRootDirTable td label .filepath, #addRootDirTable td label .filepath,
.grey-text{ .grey-text{color:#999}
color:#999 .highlight-text{color:#fff}
}
#newShowPortal #displayText .show-name, #newShowPortal #displayText .show-name,
#newShowPortal #displayText .show-dest, #newShowPortal #displayText .show-dest,
@ -314,7 +324,7 @@ home_newShow.tmpl
#newShowPortal #displayText .show-name, #newShowPortal #displayText .show-name,
#newShowPortal #displayText .show-dest{ #newShowPortal #displayText .show-dest{
color:rgb(255, 255, 255) color:#ddd
} }
/* ======================================================================= /* =======================================================================
@ -343,9 +353,28 @@ home_postprocess.tmpl
========================================================================== */ ========================================================================== */
/* =======================================================================
displayShow.tmpl and episodeView.tmpl
========================================================================== */
#episode-view.back-art .controlsBlock,
#episode-view.back-art .h2footer,
#episode-view.back-art.daybyday h1.header,
#episode-view.back-art.pro .daybyday-show,
#display-show.back-art #change-show,
#display-show.back-art #change-status,
#display-show.back-art #no-episode-data,
body.back-art .footer,
#display-show.back-art .sickbeardTable{
background:rgba(0, 0, 0, 0.5)
}
/* ======================================================================= /* =======================================================================
displayShow.tmpl displayShow.tmpl
========================================================================== */ ========================================================================== */
body#display-show.back-art{
color:#ddd
}
tr.seasonheader{ tr.seasonheader{
text-align:left; text-align:left;
@ -355,51 +384,88 @@ tr.seasonheader{
#prevShow, #prevShow,
#nextShow, #nextShow,
#topcontrol{ #topcontrol{
-webkit-filter:"none"; -webkit-filter:none;
filter:none filter:none
} }
.tvshowImg{ #posterCol .tvshowImg{
border:1px solid #111 border:1px solid #111
} }
.display-details{ body#display-show.back-art .displayshow-wrapper .label a{
background-color:#3d3d3d; color:#ddd
border:1px solid #111 }
body#display-show.back-art .displayshow-wrapper .label a:hover,
body#display-show.back-art .displayshow-wrapper .label a:focus{
color:#aaa
} }
.pro .details-title{ #edit-show.back-art .ui-tabs-nav > :not(.ui-tabs-active){
color:#999 background:rgba(0,0,0,0.2)
} }
.back-art.pro .details-title{ #edit-show.back-art .ui-tabs-nav .ui-tabs-active,
color:#bbb #edit-show.back-art .ui-tabs .ui-tabs-panel{
background:rgba(0,0,0,0.8) !important
}
#edit-show.back-art .header,
#display-show.back-art #showCol{
background:rgba(0,0,0,0.5);
border:1px solid rgba(0,0,0,0.5)
}
#livepanel .over-layer0,
#showCol{
background-color:#3d3d3d
}
#livepanel .over-layer0,
#livepanel .over-layer1,
#showCol{
border-color:#111
}
.back-art #livepanel .over-layer0{
background:rgba(0,0,0,0.5);
border-color:rgba(0,0,0,0.5)
}
.pro .details-title,
.pro .hint{
color:#aaa
} }
.back-art #details-top .label, .back-art #details-top .label,
.back-art #details-bottom .label{ .back-art #details-bottom .label{
background-color:#15528F background-color:#15528f
} }
#details-top .label, #details-top .label,
#details-bottom .label{ #details-bottom .label{
background-color:#15528F background-color:#15528f
} }
.paused-highlight{ .paused-highlight{
color:#09A2FF color:#09a2ff
} }
.sickbeardTable th{ .sickbeardTable th{
background-color:#15528f background-color:#15528f
} }
.back-art th.row-seasonheader h3,
.displayshow-wrapper .sickbeardTable th.row-seasonheader{ .displayshow-wrapper .sickbeardTable th.row-seasonheader{
color:#fff color:#ddd
} }
.back-art.pro .sickbeardTable .seasoncols th, .back-art.pro.ii .navbar-default,
.translucent.pro .sickbeardTable .seasoncols th{ .back-art.pro.ii .day-of-week .day-number,
.translucent.pro.ii .day-of-week .day-number,
.back-art.pro.ii .sickbeardTable .seasoncols th,
.translucent.pro.ii .sickbeardTable .seasoncols th,
.back-art.pro.ii .sickbeardTable thead .seasoncols td,
.translucent.pro.ii .sickbeardTable thead .seasoncols td{
background-color:rgba(21, 82, 143, 0.5) background-color:rgba(21, 82, 143, 0.5)
} }
@ -408,19 +474,19 @@ episodeView.tmpl
========================================================================== */ ========================================================================== */
h2.day, h2.network{ h2.day, h2.network{
color:#FFF; color:#ddd;
text-shadow:-1px -1px 0 rgba(0, 0, 0, 0.3); text-shadow:-1px -1px 0 rgba(0, 0, 0, 0.3);
background-color:#15528F background-color:#15528f
} }
.tvshowDiv{ .tvshowDiv{
border:1px solid #ccc; border:1px solid #ccc;
background:#fff; background:#ddd;
color:#000 color:#000
} }
.tvshowDiv a:hover{ .tvshowDiv a:hover{
color:#09A2FF color:#09a2ff
} }
.tvshowTitle a{ .tvshowTitle a{
@ -450,12 +516,12 @@ h2.day, h2.network{
#showListTable td.tvShow a:hover{ #showListTable td.tvShow a:hover{
cursor:pointer; cursor:pointer;
color:#09A2FF color:#09a2ff
} }
.day-of-week .day-number{ .day-of-week .day-number{
background-color:#15528F; background-color:#15528f;
color:#fff color:#ddd
} }
.today .day-number .number, .today .day-number .month, .today .day-number .day{ .today .day-number .number, .today .day-number .month, .today .day-number .day{
@ -477,7 +543,7 @@ h2.day, h2.network{
.day-of-week .text .airtime, .day-of-week .text .airtime,
.day-of-week .text .episode, .day-of-week .text .episode,
.day-of-week .text .episode .name{ .day-of-week .text .episode .name{
color:#fff color:#ddd
} }
.day-of-week .text .episode .season, .day-of-week .text .episode .season,
@ -506,14 +572,14 @@ h2.day, h2.network{
} }
.carousel-control{ .carousel-control{
color:#297AB8; color:#297ab8;
filter:alpha(opacity=100); filter:alpha(opacity=100);
opacity:1 opacity:1
} }
.carousel-control:hover, .carousel-control:hover,
.carousel-control:focus{ .carousel-control:focus{
color:#15528F; color:#15528f;
filter:alpha(opacity=100); filter:alpha(opacity=100);
opacity:1 opacity:1
} }
@ -524,8 +590,8 @@ h2.day, h2.network{
} }
.carousel-indicators .active{ .carousel-indicators .active{
background:#8DBEEE; background:#8dbeee;
border-color:#8DBEEE border-color:#8dbeee
} }
/* ======================================================================= /* =======================================================================
@ -554,13 +620,16 @@ config*.tmpl
} }
.testNotification{ .testNotification{
border:1px dotted #CCC border:1px dotted #ccc
} }
#provider_order_list li, #provider_order_list li,
#service_order_list li{
color:#ddd
}
#service_order_list li{ #service_order_list li{
background:#333 !important; background:#333 !important;
color:#fff
} }
.infoTableSeperator{ .infoTableSeperator{
@ -581,14 +650,23 @@ config_postProcessing.tmpl
border-color:#111 border-color:#111
} }
.back-art #config .episode-sample{
background:rgba(34,34,34,0.8);
border-color:rgba(17,17,17,0.8)
}
.back-art #config .example{
background:rgba(33,33,33,0.8);
border-color:rgba(11,11,11,0.8);
line-height: 24px
}
.Key{ .Key{
background-color:#3d3d3d; background-color:#3d3d3d;
border:1px solid #111 border:1px solid #111
} }
.Key th, .tableHeader{ .Key th, .tableHeader{
color:#fff; color:#ddd;
background:#15528F background:#15528f
} }
.Key tr{ .Key tr{
@ -605,17 +683,17 @@ config_notifications.tmpl
div.metadata_options{ div.metadata_options{
background:#333; background:#333;
color:#fff; color:#ddd;
border:1px solid #111 border:1px solid #111
} }
div.metadata_options label:hover{ div.metadata_options label:hover{
color:#fff; color:#ddd;
background-color:#15528F background-color:#15528f
} }
div.metadata_options label{ div.metadata_options label{
color:#fff color:#ddd
} }
div.metadata_example{ div.metadata_example{
@ -623,7 +701,7 @@ div.metadata_example{
} }
div.metadata_example label{ div.metadata_example label{
color:#fff color:#ddd
} }
div.metadataDiv .disabled{ div.metadataDiv .disabled{
@ -631,8 +709,8 @@ div.metadataDiv .disabled{
} }
.warning{ .warning{
border-color:#F89406; border-color:#f89406;
background:url("../images/warning16.png") no-repeat right 5px center #fff background:url("../images/warning16.png") no-repeat right 5px center #ddd
} }
.solid-border{ .solid-border{
@ -648,7 +726,7 @@ manage*.tmpl
========================================================================== */ ========================================================================== */
.separator{ .separator{
color:#fff color:#ddd
} }
a.whitelink{ a.whitelink{
@ -660,7 +738,7 @@ a.whitelink{
========================================================================== */ ========================================================================== */
#error-404 path{ #error-404 path{
fill:#fff fill:#ddd
} }
/* ======================================================================= /* =======================================================================
@ -668,7 +746,7 @@ Global
========================================================================== */ ========================================================================== */
span.path{ span.path{
color:#09A2FF; color:#09a2ff;
background-color:#333 background-color:#333
} }
@ -687,7 +765,7 @@ body{
body, body,
.show-date{ .show-date{
color:#fff color:#ddd
} }
input, textarea, select, .uneditable-input{ input, textarea, select, .uneditable-input{
@ -697,24 +775,24 @@ input, textarea, select, .uneditable-input{
/* navbar styling */ /* navbar styling */
.navbar-default{ .navbar-default{
background-color:#15528F; background-color:#15528f;
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#297AB8', endColorstr='#15528F'); filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#297ab8", endColorstr="#15528f");
background-image:-ms-linear-gradient(top, #297AB8 0%, #15528F 100%); background-image:-ms-linear-gradient(top, #297ab8 0%, #15528f 100%);
background-image:-moz-linear-gradient(top, #297AB8 0%, #15528F 100%); background-image:-moz-linear-gradient(top, #297ab8 0%, #15528f 100%);
background-image:-o-linear-gradient(top, #297AB8 0%, #15528F 100%); background-image:-o-linear-gradient(top, #297ab8 0%, #15528f 100%);
background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #297AB8), color-stop(1, #15528F)); background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0, #297ab8), color-stop(1, #15528f));
background-image:-webkit-linear-gradient(top, #297AB8 0%, #15528F 100%); background-image:-webkit-linear-gradient(top, #297ab8 0%, #15528f 100%);
background-image:linear-gradient(to bottom, #297AB8 0%, #15528F 100%); background-image:linear-gradient(to bottom, #297ab8 0%, #15528f 100%);
border-color:#3e3f3a border-color:#3e3f3a
} }
.navbar-default .navbar-brand{ .navbar-default .navbar-brand{
color:#fff color:#ddd
} }
.navbar-default .navbar-brand:hover, .navbar-default .navbar-brand:hover,
.navbar-default .navbar-brand:focus{ .navbar-default .navbar-brand:focus{
color:#fff; color:#ddd;
background-color:transparent background-color:transparent
} }
@ -728,14 +806,14 @@ input, textarea, select, .uneditable-input{
.navbar-default .navbar-nav > li > a:hover, .navbar-default .navbar-nav > li > a:hover,
.navbar-default .navbar-nav > li > a:focus{ .navbar-default .navbar-nav > li > a:focus{
color:#fff; color:#ddd;
background-color:#124477 background-color:#124477
} }
.navbar-default .navbar-nav > .active > a, .navbar-default .navbar-nav > .active > a,
.navbar-default .navbar-nav > .active > a:hover, .navbar-default .navbar-nav > .active > a:hover,
.navbar-default .navbar-nav > .active > a:focus{ .navbar-default .navbar-nav > .active > a:focus{
color:#fff; color:#ddd;
background-color:#124477 background-color:#124477
} }
@ -768,7 +846,7 @@ input, textarea, select, .uneditable-input{
.navbar-default .navbar-nav > .open > a:hover, .navbar-default .navbar-nav > .open > a:hover,
.navbar-default .navbar-nav > .open > a:focus{ .navbar-default .navbar-nav > .open > a:focus{
background-color:#124477; background-color:#124477;
color:#fff color:#ddd
} }
@media (max-width:767px){ @media (max-width:767px){
@ -777,13 +855,13 @@ input, textarea, select, .uneditable-input{
} }
.navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,
.navbar-default .navbar-nav .open .dropdown-menu > li > a:focus{ .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus{
color:#fff; color:#ddd;
background-color:transparent background-color:transparent
} }
.navbar-default .navbar-nav .open .dropdown-menu > .active > a, .navbar-default .navbar-nav .open .dropdown-menu > .active > a,
.navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,
.navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus{ .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus{
color:#fff; color:#ddd;
background-color:#124477 background-color:#124477
} }
.navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,
@ -799,7 +877,7 @@ input, textarea, select, .uneditable-input{
} }
.navbar-default .navbar-link:hover{ .navbar-default .navbar-link:hover{
color:#fff color:#ddd
} }
.navbar-default .btn-link{ .navbar-default .btn-link{
@ -819,13 +897,13 @@ fieldset[disabled] .navbar-default .btn-link:focus{
} }
.dropdown-menu > li > a:hover, .dropdown-menu > li > a:focus{ .dropdown-menu > li > a:hover, .dropdown-menu > li > a:focus{
color:#fff; color:#ddd;
text-decoration:none; text-decoration:none;
background-color:#15528F background-color:#15528f
} }
.dropdown-menu > li > a{ .dropdown-menu > li > a{
color:#fff color:#ddd
} }
.dropdown-menu{ .dropdown-menu{
@ -834,26 +912,29 @@ fieldset[disabled] .navbar-default .btn-link:focus{
box-shadow:0 6px 12px rgba(0, 0, 0, 0.176) box-shadow:0 6px 12px rgba(0, 0, 0, 0.176)
} }
.img-trakt-16{background-image:url("../images/addshows/trakt16-white.png")}
.img-import-16{background-image:url("../images/addshows/add-existing16-white.png")}
.form-control{ .form-control{
color:#000 color:#000
} }
.btn{ .btn{
color:#fff; color:#ddd;
text-shadow:0 1px 1px rgba(0, 0, 0, 0.75); text-shadow:0 1px 1px rgba(0, 0, 0, 0.75);
background-color:#2672B6; background-color:#2672b6;
*background-color:#2672B6; *background-color:#2672b6;
background-image:-ms-linear-gradient(top, #297AB8, #15528F); background-image:-ms-linear-gradient(top, #297ab8, #15528f);
background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#297AB8), to(#15528F)); background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#297ab8), to(#15528f));
background-image:-webkit-linear-gradient(top, #297AB8, #15528F); background-image:-webkit-linear-gradient(top, #297ab8, #15528f);
background-image:-o-linear-gradient(top, #297AB8, #15528F); background-image:-o-linear-gradient(top, #297ab8, #15528f);
background-image:linear-gradient(top, #297AB8, #15528F); background-image:linear-gradient(top, #297ab8, #15528f);
background-image:-moz-linear-gradient(top, #297AB8, #15528F); background-image:-moz-linear-gradient(top, #297ab8, #15528f);
border:1px solid #111; border:1px solid #111;
border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
border-color:#111 #111 #111; border-color:#111 #111 #111;
border-bottom-color:#111; border-bottom-color:#111;
filter:progid:dximagetransform.microsoft.gradient(startColorstr='#297AB8', endColorstr='#15528F', GradientType=0); filter:progid:dximagetransform.microsoft.gradient(startcolorstr="#297ab8", endcolorstr="#15528f", gradienttype=0);
filter:progid:dximagetransform.microsoft.gradient(enabled=false); filter:progid:dximagetransform.microsoft.gradient(enabled=false);
-webkit-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.0), 0 1px 2px rgba(0, 0, 0, 0.05); -webkit-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.0), 0 1px 2px rgba(0, 0, 0, 0.05);
-moz-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.0), 0 1px 2px rgba(0, 0, 0, 0.05); -moz-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.0), 0 1px 2px rgba(0, 0, 0, 0.05);
@ -865,21 +946,21 @@ fieldset[disabled] .navbar-default .btn-link:focus{
.btn.active, .btn.active,
.btn.disabled, .btn.disabled,
.btn[disabled]{ .btn[disabled]{
background-color:#2672B6; background-color:#2672b6;
*background-color:#2672B6; *background-color:#2672b6;
color:#fff color:#ddd
} }
.btn:active, .btn:active,
.btn.active{ .btn.active{
background-color:#ccc \9; background-color:#ccc \9;
color:#fff color:#ddd
} }
.btn:hover{ .btn:hover{
color:#fff; color:#ddd;
background-color:#2672B6; background-color:#2672b6;
*background-color:#2672B6; *background-color:#2672b6;
background-position:0 -150px; background-position:0 -150px;
-webkit-transition:background-position 0.0s linear; -webkit-transition:background-position 0.0s linear;
-moz-transition:background-position 0.0s linear; -moz-transition:background-position 0.0s linear;
@ -892,15 +973,15 @@ fieldset[disabled] .navbar-default .btn-link:focus{
outline:thin dotted #333; outline:thin dotted #333;
outline:5px auto -webkit-focus-ring-color; outline:5px auto -webkit-focus-ring-color;
outline-offset:-2px; outline-offset:-2px;
color:#fff color:#ddd
} }
.btn.active, .btn.active,
.btn:active{ .btn:active{
background-color:#2672B6; background-color:#2672b6;
background-color:#2672B6 \9; background-color:#2672b6 \9;
background-image:none; background-image:none;
color:#fff; color:#ddd;
outline:0; outline:0;
-webkit-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); -webkit-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
-moz-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); -moz-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
@ -910,7 +991,7 @@ fieldset[disabled] .navbar-default .btn-link:focus{
.btn.disabled, .btn.disabled,
.btn[disabled]{ .btn[disabled]{
cursor:default; cursor:default;
background:#15528F none; background:#15528f none;
opacity:0.65; opacity:0.65;
filter:alpha(opacity=65); filter:alpha(opacity=65);
-webkit-box-shadow:none; -webkit-box-shadow:none;
@ -940,13 +1021,15 @@ fieldset[disabled] .navbar-default .btn-link:focus{
.btn-warning:hover, .btn-warning:hover,
.btn-danger, .btn-danger,
.btn-danger:hover, .btn-danger:hover,
.ui-widget-content .btn-danger,
.ui-widget-content .btn-danger:hover,
.btn-success, .btn-success,
.btn-success:hover, .btn-success:hover,
.btn-info, .btn-info,
.btn-info:hover, .btn-info:hover,
.btn-inverse, .btn-inverse,
.btn-inverse:hover{ .btn-inverse:hover{
color:#fff; color:#ddd;
text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25) text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25)
} }
@ -971,7 +1054,7 @@ fieldset[disabled] .navbar-default .btn-link:focus{
background-repeat:repeat-x; background-repeat:repeat-x;
border-color:#0055cc #0055cc #003580; border-color:#0055cc #0055cc #003580;
border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
filter:progid:dximagetransform.microsoft.gradient(startColorstr='#0088cc', endColorstr='#0055cc', GradientType=0); filter:progid:dximagetransform.microsoft.gradient(startColorstr="#0088cc", endColorstr="#0055cc", GradientType=0);
filter:progid:dximagetransform.microsoft.gradient(enabled=false) filter:progid:dximagetransform.microsoft.gradient(enabled=false)
} }
@ -1001,7 +1084,7 @@ fieldset[disabled] .navbar-default .btn-link:focus{
background-repeat:repeat-x; background-repeat:repeat-x;
border-color:#f89406 #f89406 #ad6704; border-color:#f89406 #f89406 #ad6704;
border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
filter:progid:dximagetransform.microsoft.gradient(startColorstr='#fbb450', endColorstr='#f89406', GradientType=0); filter:progid:dximagetransform.microsoft.gradient(startColorstr="#fbb450", endColorstr="#f89406", GradientType=0);
filter:progid:dximagetransform.microsoft.gradient(enabled=false) filter:progid:dximagetransform.microsoft.gradient(enabled=false)
} }
@ -1031,7 +1114,7 @@ fieldset[disabled] .navbar-default .btn-link:focus{
background-repeat:repeat-x; background-repeat:repeat-x;
border-color:#bd362f #bd362f #802420; border-color:#bd362f #bd362f #802420;
border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#bd362f', GradientType=0); filter:progid:dximagetransform.microsoft.gradient(startColorstr="#ee5f5b", endColorstr="#bd362f", GradientType=0);
filter:progid:dximagetransform.microsoft.gradient(enabled=false) filter:progid:dximagetransform.microsoft.gradient(enabled=false)
} }
@ -1061,7 +1144,7 @@ fieldset[disabled] .navbar-default .btn-link:focus{
background-repeat:repeat-x; background-repeat:repeat-x;
border-color:#51a351 #51a351 #387038; border-color:#51a351 #51a351 #387038;
border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
filter:progid:dximagetransform.microsoft.gradient(startColorstr='#62c462', endColorstr='#51a351', GradientType=0); filter:progid:dximagetransform.microsoft.gradient(startColorstr="#62c462", endColorstr="#51a351", GradientType=0);
filter:progid:dximagetransform.microsoft.gradient(enabled=false) filter:progid:dximagetransform.microsoft.gradient(enabled=false)
} }
@ -1091,7 +1174,7 @@ fieldset[disabled] .navbar-default .btn-link:focus{
background-repeat:repeat-x; background-repeat:repeat-x;
border-color:#2f96b4 #2f96b4 #1f6377; border-color:#2f96b4 #2f96b4 #1f6377;
border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
filter:progid:dximagetransform.microsoft.gradient(startColorstr='#5bc0de', endColorstr='#2f96b4', GradientType=0); filter:progid:dximagetransform.microsoft.gradient(startColorstr="#5bc0de", endColorstr="#2f96b4", GradientType=0);
filter:progid:dximagetransform.microsoft.gradient(enabled=false) filter:progid:dximagetransform.microsoft.gradient(enabled=false)
} }
@ -1121,7 +1204,7 @@ fieldset[disabled] .navbar-default .btn-link:focus{
background-repeat:repeat-x; background-repeat:repeat-x;
border-color:#222 #222 #000; border-color:#222 #222 #000;
border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
filter:progid:dximagetransform.microsoft.gradient(startColorstr='#555555', endColorstr='#222222', GradientType=0); filter:progid:dximagetransform.microsoft.gradient(startColorstr="#555555", endColorstr="#222222", GradientType=0);
filter:progid:dximagetransform.microsoft.gradient(enabled=false) filter:progid:dximagetransform.microsoft.gradient(enabled=false)
} }
@ -1160,9 +1243,9 @@ fieldset[disabled] .navbar-default .btn-link:focus{
.navbar-default .navbar-nav > .active > a{ .navbar-default .navbar-nav > .active > a{
background-color:transparent; background-color:transparent;
-webkit-box-shadow:inset 0px -5px 0px 0px #8DBEEE; -webkit-box-shadow:inset 0px -5px 0px 0px #8dbeee;
-moz-box-shadow:inset 0px -5px 0px 0px #8DBEEE; -moz-box-shadow:inset 0px -5px 0px 0px #8dbeee;
box-shadow:inset 0px -5px 0px 0px #8DBEEE box-shadow:inset 0px -5px 0px 0px #8dbeee
} }
.navbar-fixed-top{ .navbar-fixed-top{
@ -1171,7 +1254,7 @@ fieldset[disabled] .navbar-default .btn-link:focus{
} }
pre{ pre{
color:#fff; color:#ddd;
background-color:#3d3d3d; background-color:#3d3d3d;
border-color:#111 border-color:#111
} }
@ -1193,7 +1276,7 @@ input sizing (for config pages)
#showfilter optgroup option, #showfilter optgroup option,
#editAProvider optgroup option{ #editAProvider optgroup option{
color:#222; color:#222;
background-color:#fff background-color:#ddd
} }
/* ======================================================================= /* =======================================================================
@ -1206,7 +1289,7 @@ browser.css
#fileBrowserDialog ul li a:hover{ #fileBrowserDialog ul li a:hover{
color:#09a2ff; color:#09a2ff;
background: rgb(61, 61, 61) none background:rgb(61, 61, 61) none
} }
.ui-menu .ui-menu-item{ .ui-menu .ui-menu-item{
@ -1214,11 +1297,11 @@ browser.css
} }
.ui-menu .ui-menu-item-alternate{ .ui-menu .ui-menu-item-alternate{
background-color:#fff background-color:#ddd
} }
.ui-autocomplete .ui-menu-item .ui-state-focus{ .ui-autocomplete .ui-menu-item .ui-state-focus{
color:#fff; color:#ddd;
background:none; background:none;
background-color:#0a246a background-color:#0a246a
} }
@ -1229,11 +1312,11 @@ formWizard
.step, .step,
legend.legendStep{ legend.legendStep{
color:#fff color:#ddd
} }
div.stepsguide .step p{ div.stepsguide .step p{
border-color:#23AFDC border-color:#23afdc
} }
.disabledstep{ .disabledstep{
@ -1241,7 +1324,7 @@ div.stepsguide .step p{
} }
#newShowPortal #addShowForm .stepsguide .disabledstep:hover > .smalltext{ #newShowPortal #addShowForm .stepsguide .disabledstep:hover > .smalltext{
color:#ccc; color:#ccc
} }
.stepDiv #searchResults div .exists-db{ .stepDiv #searchResults div .exists-db{
@ -1249,16 +1332,16 @@ div.stepsguide .step p{
} }
div.stepsguide .disabledstep p{ div.stepsguide .disabledstep p{
border-color:#1178B3 border-color:#1178b3
} }
div.formpaginate .prev, div.formpaginate .next{ div.formpaginate .prev, div.formpaginate .next{
color:#fff; color:#ddd;
background:#2265A1 background:#2265a1
} }
#customQualityWrapper .tip-text p{ #customQualityWrapper .tip-text p{
color:#888 color:#999
} }
/* ======================================================================= /* =======================================================================
@ -1276,11 +1359,11 @@ pnotify.css
} }
.ui-pnotify-title{ .ui-pnotify-title{
color:#fff color:#ddd
} }
.ui-pnotify-text{ .ui-pnotify-text{
color:#fff color:#ddd
} }
/* ======================================================================= /* =======================================================================
@ -1288,7 +1371,7 @@ tablesorter.css
========================================================================== */ ========================================================================== */
.tablesorter{ .tablesorter{
color:#fff; color:#ddd;
background-color:#333 background-color:#333
} }
@ -1303,25 +1386,26 @@ tablesorter.css
border-left:none border-left:none
} }
.tablesorter th{ .tablesorter th,
color:#fff; .sickbeardTable thead .seasoncols td{
color:#ddd;
text-shadow:-1px -1px 0 rgba(0, 0, 0, 0.3); text-shadow:-1px -1px 0 rgba(0, 0, 0, 0.3);
background-color:#15528F background-color:#15528f
} }
.tablesorter .tablesorter-header{ .tablesorter .tablesorter-header{
background:#15528F url(data:image/gif;base64,R0lGODlhFQAJAIAAAP///////yH5BAEAAAEALAAAAAAVAAkAAAIXjI+AywnaYnhUMoqt3gZXPmVg94yJVQAAOw==) no-repeat center right; background:#15528f url("data:image/gif;base64,R0lGODlhFQAJAIAAAP///////yH5BAEAAAEALAAAAAAVAAkAAAIXjI+AywnaYnhUMoqt3gZXPmVg94yJVQAAOw==") no-repeat center right;
/* background-image:url(../images/tablesorter/bg.gif) */ /* background-image:url("../images/tablesorter/bg.gif") */
} }
.tablesorter thead .tablesorter-headerDesc{ .tablesorter thead .tablesorter-headerDesc{
background:#297AB8 url(data:image/gif;base64,R0lGODlhFQAEAIAAAP///////yH5BAEAAAEALAAAAAAVAAQAAAINjB+gC+jP2ptn0WskLQA7) no-repeat center right; background:#297ab8 url("data:image/gif;base64,R0lGODlhFQAEAIAAAP///////yH5BAEAAAEALAAAAAAVAAQAAAINjB+gC+jP2ptn0WskLQA7") no-repeat center right;
/* background-image:url(../images/tablesorter/asc.gif) */ /* background-image:url("../images/tablesorter/asc.gif") */
} }
.tablesorter thead .tablesorter-headerAsc{ .tablesorter thead .tablesorter-headerAsc{
background:#297AB8 url(data:image/gif;base64,R0lGODlhFQAEAIAAAP///////yH5BAEAAAEALAAAAAAVAAQAAAINjI8Bya2wnINUMopZAQA7) no-repeat center right; background:#297ab8 url("data:image/gif;base64,R0lGODlhFQAEAIAAAP///////yH5BAEAAAEALAAAAAAVAAQAAAINjI8Bya2wnINUMopZAQA7") no-repeat center right;
/* background-image:url(../images/tablesorter/desc.gif) */ /* background-image:url("../images/tablesorter/desc.gif") */
} }
thead.tablesorter-stickyHeader{ thead.tablesorter-stickyHeader{
@ -1329,11 +1413,16 @@ thead.tablesorter-stickyHeader{
border-bottom:2px solid #222 border-bottom:2px solid #222
} }
.ui-state-default.row-odd{
background-color:#363636
}
/* Zebra Widget - row alternating colors */ /* Zebra Widget - row alternating colors */
.tablesorter tr.odd, .sickbeardTable tr.odd{ .tablesorter tr.odd, .sickbeardTable tr.odd{
background-color:#333 background-color:#333
} }
.ui-state-default.row-even,
.tablesorter tr.even, .sickbeardTable tr.even{ .tablesorter tr.even, .sickbeardTable tr.even{
background-color:#2e2e2e background-color:#2e2e2e
} }
@ -1346,7 +1435,7 @@ thead.tablesorter-stickyHeader{
} }
.tablesorter tfoot tr{ .tablesorter tfoot tr{
color:#fff; color:#ddd;
text-align:center; text-align:center;
text-shadow:-1px -1px 0 rgba(0, 0, 0, 0.3); text-shadow:-1px -1px 0 rgba(0, 0, 0, 0.3);
background-color:#333; background-color:#333;
@ -1354,7 +1443,7 @@ thead.tablesorter-stickyHeader{
} }
.tablesorter tfoot a{ .tablesorter tfoot a{
color:#fff color:#ddd
} }
#showListTable tbody{ #showListTable tbody{
@ -1368,7 +1457,7 @@ token-input.css
ul.token-input-list{ ul.token-input-list{
border:1px solid #ccc; border:1px solid #ccc;
background-color:#fff background-color:#ddd
} }
ul.token-input-list li input{ ul.token-input-list li input{
@ -1387,7 +1476,7 @@ li.token-input-token span{
li.token-input-selected-token{ li.token-input-selected-token{
background-color:#08844e; background-color:#08844e;
color:#fff color:#ddd
} }
li.token-input-selected-token span{ li.token-input-selected-token span{
@ -1395,7 +1484,7 @@ li.token-input-selected-token span{
} }
div.token-input-dropdown{ div.token-input-dropdown{
background-color:#fff; background-color:#ddd;
color:#000; color:#000;
border-left-color:#ccc; border-left-color:#ccc;
border-right-color:#ccc; border-right-color:#ccc;
@ -1407,7 +1496,7 @@ div.token-input-dropdown p{
} }
div.token-input-dropdown ul li{ div.token-input-dropdown ul li{
background-color:#fff background-color:#ddd
} }
div.token-input-dropdown ul li.token-input-dropdown-item{ div.token-input-dropdown ul li.token-input-dropdown-item{
@ -1415,7 +1504,7 @@ div.token-input-dropdown ul li.token-input-dropdown-item{
} }
div.token-input-dropdown ul li.token-input-dropdown-item2{ div.token-input-dropdown ul li.token-input-dropdown-item2{
background-color:#fff background-color:#ddd
} }
div.token-input-dropdown ul li.token-input-selected-dropdown-item{ div.token-input-dropdown ul li.token-input-selected-dropdown-item{
@ -1427,7 +1516,7 @@ jquery.confirm.css
========================================================================== */ ========================================================================== */
#confirmOverlay{ #confirmOverlay{
background:url('../images/bg.gif'); background:url("../images/bg.gif");
background:-moz-linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)) repeat-x rgba(0, 0, 0, 0.5); background:-moz-linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)) repeat-x rgba(0, 0, 0, 0.5);
background:-webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0.5))) repeat-x rgba(0, 0, 0, 0.5); background:-webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0.5))) repeat-x rgba(0, 0, 0, 0.5);
z-index:100000 z-index:100000
@ -1440,19 +1529,19 @@ jquery.confirm.css
} }
#confirmBox h1{ #confirmBox h1{
background-color:#15528F; background-color:#15528f;
border-bottom:1px solid #111; border-bottom:1px solid #111;
color:#fff; color:#ddd;
text-shadow:0 1px 1px rgba(0, 0, 0, 0.75) text-shadow:0 1px 1px rgba(0, 0, 0, 0.75)
} }
#confirmBox p{ #confirmBox p{
color:#fff; color:#ddd;
text-shadow:0 1px 1px rgba(0, 0, 0, 0.75) text-shadow:0 1px 1px rgba(0, 0, 0, 0.75)
} }
#confirmBox .button{ #confirmBox .button{
color:#fff; color:#ddd;
text-shadow:0 1px 1px rgba(0, 0, 0, 0.75); text-shadow:0 1px 1px rgba(0, 0, 0, 0.75);
border:1px solid #111; border:1px solid #111;
border-radius:3px; border-radius:3px;
@ -1465,17 +1554,17 @@ jquery.confirm.css
} }
#confirmBox .green{ #confirmBox .green{
background-color:#3F7636 background-color:#3f7636
} }
#confirmBox .green:hover{ #confirmBox .green:hover{
background-color:#48873E background-color:#48873e
} }
#confirmBox .red{ #confirmBox .red{
background-color:#8D2D2B background-color:#8d2d2b
} }
#confirmBox .red:hover{ #confirmBox .red:hover{
background-color:#A13331 background-color:#a13331
} }

Binary file not shown.

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 3.4 MiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 191 KiB

After

Width:  |  Height:  |  Size: 205 KiB

Binary file not shown.

Binary file not shown.

View file

@ -853,3 +853,21 @@ button.ui-button::-moz-focus-inner {
filter: Alpha(Opacity=35); filter: Alpha(Opacity=35);
border-radius: 8px; border-radius: 8px;
} }
.ui-tooltip {
padding:3px 6px;
position:absolute;
z-index:9999;
max-width:300px;
-webkit-box-shadow:1px 1px 3px 1px rgba(0,0,0,.15);
-moz-box-shadow:1px 1px 3px 1px rgba(0,0,0,.15);
box-shadow:1px 1px 3px 1px rgba(0,0,0,.15)
}
body .ui-tooltip {
font-size: 10px;
border-radius: 5px 5px 5px 5px;
border: 1px solid rgb(241, 208, 49);
background-color: rgb(255, 255, 163);
color: rgb(85, 85, 85)
}

View file

@ -1,14 +1,32 @@
/* ======================================================================= /* =======================================================================
inc_top.tmpl inc_top.tmpl
========================================================================== */ ========================================================================== */
.navbar-default .navbar-nav .logger.errors.n,
pre .prelight{
color:#6f8c53
}
.navbar-default .navbar-nav .logger.errors.nn,
pre .prelight2{
color:#b7b82c
}
.navbar-default .navbar-nav .logger.errors.nnn,
pre .prelight-num{
color:#eaab52
}
.navbar-default .navbar-nav .logger.errors.nnnn{
color:#ff6d5e
}
[class^="icon-"], [class^="icon-"],
[class*=" icon-"]{ [class*=" icon-"]{
background-image:url("../images/glyphicons-halflings.png") background-image:url("../images/glyphicons-halflings-white.png")
} }
.icon-white{ .icon-white{
background-image:url("../images/glyphicons-halflings-white.png") background-image:url("../images/glyphicons-halflings.png")
} }
.ui-autocomplete-loading{ .ui-autocomplete-loading{
@ -43,7 +61,7 @@ inc_top.tmpl
} }
.ui-widget-content a:hover{ .ui-widget-content a:hover{
color:#09A2FF color:#09a2ff
} }
.ui-widget-header{ .ui-widget-header{
@ -54,7 +72,7 @@ inc_top.tmpl
.ui-widget-content .ui-state-default, .ui-widget-content .ui-state-default,
.ui-widget-header .ui-state-default{ .ui-widget-header .ui-state-default{
background:#fff; background:#fff;
border:1px solid #CCC border:1px solid #ccc
} }
.ui-state-hover, .ui-state-hover,
@ -69,7 +87,7 @@ inc_top.tmpl
.ui-state-active, .ui-state-active,
.ui-widget-content .ui-state-active, .ui-widget-content .ui-state-active,
.ui-widget-header .ui-state-active{ .ui-widget-header .ui-state-active{
background:#F7F7F7 background:#f7f7f7
} }
.ui-state-highlight, .ui-state-highlight,
@ -124,7 +142,7 @@ inc_top.tmpl
} }
.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited{ .ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited{
color:#140F06; color:#140f06;
text-decoration:none text-decoration:none
} }
@ -149,8 +167,8 @@ inc_top.tmpl
} }
.ui-tabs .ui-tabs-panel{ .ui-tabs .ui-tabs-panel{
background-color:#F7F7F7 !important; background-color:#f7f7f7 !important;
border:1px solid #CCC !important border:1px solid #ccc !important
} }
.ui-tabs .ui-tabs-nav li.ui-tabs-active{ .ui-tabs .ui-tabs-nav li.ui-tabs-active{
@ -184,19 +202,30 @@ inc_bottom.tmpl
========================================================================== */ ========================================================================== */
.footerhighlight{ .footerhighlight{
color:#428BCA color:#428bca
} }
body#display-show.back-art .displayshow-wrapper a, body#display-show.back-art .displayshow-wrapper a,
body#display-show.back-art .footerhighlight a, body#display-show.back-art .footerhighlight a,
body#display-show.back-art .footerhighlight{ body#display-show.back-art .footerhighlight{
color:#c7db40 color:#288536
/* color:#c7db40
*/
} }
body#display-show.back-art .displayshow-wrapper a:hover, body#display-show.back-art .displayshow-wrapper a:hover,
body#display-show.back-art .displayshow-wrapper a:focus, body#display-show.back-art .displayshow-wrapper a:focus,
body#display-show.back-art .footerhighlight a:hover, body#display-show.back-art .footerhighlight a:hover,
body#display-show.back-art .footerhighlight a:focus{ body#display-show.back-art .footerhighlight a:focus{
color:#7C8119
/* color:#c7db40
*/
}
body#display-show.back-art .displayshow-wrapper .label a{
color:#c7db40
}
body#display-show.back-art .displayshow-wrapper .label a:hover,
body#display-show.back-art .displayshow-wrapper .label a:focus{
color:#9faf33 color:#9faf33
} }
@ -219,7 +248,7 @@ a.ui-font{
} }
#show-list .show-card{ #show-list .show-card{
background-color:#DFDACF; background-color:#dfdacf;
color:#666; color:#666;
border:1px solid #111 border:1px solid #111
} }
@ -269,7 +298,7 @@ td.tvShow a{
td.tvShow a:hover span, td.tvShow a:hover span,
td.tvShow a:hover{ td.tvShow a:hover{
cursor:pointer; cursor:pointer;
color:#428BCA color:#428bca
} }
/* ======================================================================= /* =======================================================================
@ -299,9 +328,8 @@ home_newShow.tmpl
} }
#addRootDirTable td label .filepath, #addRootDirTable td label .filepath,
.grey-text{ .grey-text{color:#666}
color:#666 .highlight-text{color:#000}
}
#newShowPortal #displayText .show-name, #newShowPortal #displayText .show-name,
#newShowPortal #displayText .show-dest, #newShowPortal #displayText .show-dest,
@ -319,7 +347,7 @@ home_addExistingShow.tmpl
========================================================================== */ ========================================================================== */
ul#rootDirStaticList li{ ul#rootDirStaticList li{
background:url('../css/lib/images/ui-bg_highlight-soft_75_efefef_1x100.png') repeat-x scroll 50% 50% #EFEFEF background:url("../css/lib/images/ui-bg_highlight-soft_75_efefef_1x100.png") repeat-x scroll 50% 50% #efefef
} }
/* ======================================================================= /* =======================================================================
@ -327,7 +355,7 @@ home_browseShows.tmpl
========================================================================== */ ========================================================================== */
#browse-list .show-card{ #browse-list .show-card{
background-color:#DFDACF; background-color:#dfdacf;
border:1px solid #111 border:1px solid #111
} }
@ -340,6 +368,21 @@ home_postprocess.tmpl
========================================================================== */ ========================================================================== */
/* =======================================================================
displayShow.tmpl and episodeView.tmpl
========================================================================== */
#episode-view.back-art .controlsBlock,
#episode-view.back-art .h2footer,
#episode-view.back-art.daybyday h1.header,
#episode-view.back-art.pro .daybyday-show,
#display-show.back-art #change-show,
#display-show.back-art #change-status,
#display-show.back-art #no-episode-data,
body.back-art .footer,
#display-show.back-art .sickbeardTable{
background-color: rgba(239, 239, 239, 0.8)
}
/* ======================================================================= /* =======================================================================
displayShow.tmpl displayShow.tmpl
========================================================================== */ ========================================================================== */
@ -358,23 +401,41 @@ tr.seasonheader{
filter:url("data:image/svg+xml;utf8,<svg version='1.1' xmlns='http://www.w3.org/2000/svg' height='0'><filter id='greyscale'><feColorMatrix type='matrix' values='0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0' /></filter></svg>#greyscale") filter:url("data:image/svg+xml;utf8,<svg version='1.1' xmlns='http://www.w3.org/2000/svg' height='0'><filter id='greyscale'><feColorMatrix type='matrix' values='0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0' /></filter></svg>#greyscale")
} }
.tvshowImg{ #posterCol .tvshowImg{
border:1px solid #ccc border: 1px solid rgba(239, 239, 239, 0.8);
} }
.display-details{ #edit-show.back-art .ui-tabs-nav > :not(.ui-tabs-active){
background-color:#efefef; background:rgba(239, 239, 239,0.4)
border:1px solid #dfdede
} }
.pro .details-title{ #edit-show.back-art .ui-tabs-nav .ui-tabs-active,
#edit-show.back-art .ui-tabs .ui-tabs-panel{
background:rgba(239, 239, 239,0.8) !important
}
#edit-show.back-art .header,
#display-show.back-art #showCol{
background:rgba(239, 239, 239, 0.8);
border:1px solid rgba(239, 239, 239, 0.8)
}
#livepanel .over-layer0,
#showCol{
background-color:#efefef
}
#livepanel .over-layer0,
#livepanel .over-layer1,
#showCol{
border-color:#dfdede
}
.pro .details-title,
.pro .hint{
color:#666 color:#666
} }
.back-art.pro .details-title{
color:#bbb
}
.back-art #details-top .label, .back-art #details-top .label,
.back-art #details-bottom .label{ .back-art #details-bottom .label{
background-color:#215f2f background-color:#215f2f
@ -386,19 +447,24 @@ tr.seasonheader{
} }
.paused-highlight{ .paused-highlight{
color:#C7DB40 color:#c7db40
} }
.sickbeardTable th{ .sickbeardTable th{
background-color:#333 background-color:#333
} }
body#display-show.back-art,
.displayshow-wrapper .sickbeardTable th.row-seasonheader{ .displayshow-wrapper .sickbeardTable th.row-seasonheader{
color:#000 color:#000
} }
.translucent.pro .sickbeardTable th{ .back-art.pro.ii .navbar-default,
background-color:rgba(51, 51, 51, 0.5) .back-art.pro.ii .day-of-week .day-number,
.translucent.pro.ii .day-of-week .day-number,
.back-art.pro.ii .sickbeardTable .seasoncols th,
.translucent.pro.ii .sickbeardTable .seasoncols th{
background-color:rgba(51, 51, 51, 0.7)
} }
/* ======================================================================= /* =======================================================================
@ -406,7 +472,7 @@ episodeView.tmpl
========================================================================== */ ========================================================================== */
h2.day, h2.network{ h2.day, h2.network{
color:#FFF; color:#fff;
text-shadow:-1px -1px 0 rgba(0, 0, 0, 0.3); text-shadow:-1px -1px 0 rgba(0, 0, 0, 0.3);
background-color:#333 background-color:#333
} }
@ -417,7 +483,7 @@ h2.day, h2.network{
} }
.tvshowDiv a:hover{ .tvshowDiv a:hover{
color:#428BCA color:#428bca
} }
.tvshowTitle a{ .tvshowTitle a{
@ -451,15 +517,15 @@ h2.day, h2.network{
} }
.odd .daybyday-show{ .odd .daybyday-show{
background-color:#F5F1E4 background-color:#f5f1e4
} }
.even .daybyday-show{ .even .daybyday-show{
background-color:#DFDACF background-color:#dfdacf
} }
.day-of-week .poster img{ .day-of-week .poster img{
border-color:#CCC border-color:#ccc
} }
.over-layer0{ .over-layer0{
@ -484,13 +550,25 @@ h2.day, h2.network{
.day-of-week .text .episode .season, .day-of-week .text .episode .season,
.day-of-week .text .episode .number{ .day-of-week .text .episode .number{
color:rgb(9, 133, 225) color:#0985e1
} }
.day-of-week .text .episode{ .day-of-week .text .episode{
color:#888 color:#888
} }
.daybyday-show .state{
height:5px
}
.daybyday-show .listing-current{
border:1px solid #1d5068
}
.daybyday-show .listing-overdue{
border:1px solid #890000
}
.episodeview-daybyday .time .time-hr-min, .episodeview-daybyday .time .time-hr-min,
.episodeview-daybyday .time .time-am-pm{ .episodeview-daybyday .time .time-am-pm{
color:#666 color:#666
@ -502,8 +580,8 @@ h2.day, h2.network{
} }
.carousel-indicators .active{ .carousel-indicators .active{
background:#C7DB40; background:#c7db40;
border-color:#C7DB40 border-color:#c7db40
} }
/* ======================================================================= /* =======================================================================
@ -532,7 +610,7 @@ config*.tmpl
} }
.testNotification{ .testNotification{
border:1px dotted #CCC border:1px dotted #ccc
} }
.infoTableSeperator{ .infoTableSeperator{
@ -553,6 +631,16 @@ config_postProcessing.tmpl
border-color:rgb(204, 204, 204) border-color:rgb(204, 204, 204)
} }
.back-art #config .episode-sample{
background:rgba(255,255,255,0.8);
border-color:rgba(204,204,204,0.8)
}
.back-art #config .example{
background:rgba(239,239,239,0.8);
border-color:rgba(204,204,204,0.8);
line-height: 24px
}
.Key{ .Key{
background-color:#f4f4f4; background-color:#f4f4f4;
border:1px solid #ccc border:1px solid #ccc
@ -602,7 +690,7 @@ div.metadataDiv .disabled{
} }
.warning{ .warning{
border-color:#F89406; border-color:#f89406;
background:url("../images/warning16.png") no-repeat right 5px center #fff background:url("../images/warning16.png") no-repeat right 5px center #fff
} }
@ -665,7 +753,7 @@ input, textarea, select, .uneditable-input{
/* navbar styling */ /* navbar styling */
.navbar-default{ .navbar-default{
background-color:#333; background-color:#333;
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#555555', endColorstr='#333333'); filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#555555", endColorstr="#333333");
background-image:-ms-linear-gradient(top, #555555 0%, #333333 100%); background-image:-ms-linear-gradient(top, #555555 0%, #333333 100%);
background-image:-moz-linear-gradient(top, #555555 0%, #333333 100%); background-image:-moz-linear-gradient(top, #555555 0%, #333333 100%);
background-image:-o-linear-gradient(top, #555555 0%, #333333 100%); background-image:-o-linear-gradient(top, #555555 0%, #333333 100%);
@ -792,7 +880,7 @@ fieldset[disabled] .navbar-default .btn-link:focus{
} }
.dropdown-menu{ .dropdown-menu{
background-color:#F5F1E4; background-color:#f5f1e4;
border:1px solid rgba(0, 0, 0, 0.15); border:1px solid rgba(0, 0, 0, 0.15);
box-shadow:0 6px 12px rgba(0, 0, 0, 0.176) box-shadow:0 6px 12px rgba(0, 0, 0, 0.176)
} }
@ -816,7 +904,7 @@ fieldset[disabled] .navbar-default .btn-link:focus{
border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
border-color:#e6e6e6 #e6e6e6 #bfbfbf; border-color:#e6e6e6 #e6e6e6 #bfbfbf;
border-bottom-color:#b3b3b3; border-bottom-color:#b3b3b3;
filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0); filter:progid:dximagetransform.microsoft.gradient(startColorstr="#ffffff", endColorstr="#e6e6e6", GradientType=0);
filter:progid:dximagetransform.microsoft.gradient(enabled=false); filter:progid:dximagetransform.microsoft.gradient(enabled=false);
-webkit-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -webkit-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
-moz-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -moz-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
@ -899,6 +987,8 @@ fieldset[disabled] .navbar-default .btn-link:focus{
.btn-warning:hover, .btn-warning:hover,
.btn-danger, .btn-danger,
.btn-danger:hover, .btn-danger:hover,
.ui-widget-content .btn-danger,
.ui-widget-content .btn-danger:hover,
.btn-success, .btn-success,
.btn-success:hover, .btn-success:hover,
.btn-info, .btn-info,
@ -930,7 +1020,7 @@ fieldset[disabled] .navbar-default .btn-link:focus{
background-repeat:repeat-x; background-repeat:repeat-x;
border-color:#0055cc #0055cc #003580; border-color:#0055cc #0055cc #003580;
border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
filter:progid:dximagetransform.microsoft.gradient(startColorstr='#0088cc', endColorstr='#0055cc', GradientType=0); filter:progid:dximagetransform.microsoft.gradient(startColorstr="#0088cc", endColorstr="#0055cc", GradientType=0);
filter:progid:dximagetransform.microsoft.gradient(enabled=false) filter:progid:dximagetransform.microsoft.gradient(enabled=false)
} }
@ -960,7 +1050,7 @@ fieldset[disabled] .navbar-default .btn-link:focus{
background-repeat:repeat-x; background-repeat:repeat-x;
border-color:#f89406 #f89406 #ad6704; border-color:#f89406 #f89406 #ad6704;
border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
filter:progid:dximagetransform.microsoft.gradient(startColorstr='#fbb450', endColorstr='#f89406', GradientType=0); filter:progid:dximagetransform.microsoft.gradient(startColorstr="#fbb450", endColorstr="#f89406", GradientType=0);
filter:progid:dximagetransform.microsoft.gradient(enabled=false) filter:progid:dximagetransform.microsoft.gradient(enabled=false)
} }
@ -990,7 +1080,7 @@ fieldset[disabled] .navbar-default .btn-link:focus{
background-repeat:repeat-x; background-repeat:repeat-x;
border-color:#bd362f #bd362f #802420; border-color:#bd362f #bd362f #802420;
border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
filter:progid:dximagetransform.microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#bd362f', GradientType=0); filter:progid:dximagetransform.microsoft.gradient(startColorstr="#ee5f5b", endColorstr="#bd362f", GradientType=0);
filter:progid:dximagetransform.microsoft.gradient(enabled=false) filter:progid:dximagetransform.microsoft.gradient(enabled=false)
} }
@ -1020,7 +1110,7 @@ fieldset[disabled] .navbar-default .btn-link:focus{
background-repeat:repeat-x; background-repeat:repeat-x;
border-color:#51a351 #51a351 #387038; border-color:#51a351 #51a351 #387038;
border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
filter:progid:dximagetransform.microsoft.gradient(startColorstr='#62c462', endColorstr='#51a351', GradientType=0); filter:progid:dximagetransform.microsoft.gradient(startColorstr="#62c462", endColorstr="#51a351", GradientType=0);
filter:progid:dximagetransform.microsoft.gradient(enabled=false) filter:progid:dximagetransform.microsoft.gradient(enabled=false)
} }
@ -1050,7 +1140,7 @@ fieldset[disabled] .navbar-default .btn-link:focus{
background-repeat:repeat-x; background-repeat:repeat-x;
border-color:#2f96b4 #2f96b4 #1f6377; border-color:#2f96b4 #2f96b4 #1f6377;
border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
filter:progid:dximagetransform.microsoft.gradient(startColorstr='#5bc0de', endColorstr='#2f96b4', GradientType=0); filter:progid:dximagetransform.microsoft.gradient(startColorstr="#5bc0de", endColorstr="#2f96b4", GradientType=0);
filter:progid:dximagetransform.microsoft.gradient(enabled=false) filter:progid:dximagetransform.microsoft.gradient(enabled=false)
} }
@ -1080,7 +1170,7 @@ fieldset[disabled] .navbar-default .btn-link:focus{
background-repeat:repeat-x; background-repeat:repeat-x;
border-color:#222 #222 #000; border-color:#222 #222 #000;
border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
filter:progid:dximagetransform.microsoft.gradient(startColorstr='#555555', endColorstr='#222222', GradientType=0); filter:progid:dximagetransform.microsoft.gradient(startColorstr="#555555", endColorstr="#222222", GradientType=0);
filter:progid:dximagetransform.microsoft.gradient(enabled=false) filter:progid:dximagetransform.microsoft.gradient(enabled=false)
} }
@ -1112,16 +1202,16 @@ fieldset[disabled] .navbar-default .btn-link:focus{
right:12px; right:12px;
display:inline-block; display:inline-block;
border-right:6px solid transparent; border-right:6px solid transparent;
border-bottom:6px solid #F5F1E4; border-bottom:6px solid #f5f1e4;
border-left:6px solid transparent; border-left:6px solid transparent;
content:"" content:""
} }
.navbar-default .navbar-nav > .active > a{ .navbar-default .navbar-nav > .active > a{
background-color:transparent; background-color:transparent;
-webkit-box-shadow:inset 0px -5px 0px 0px #C7DB40; -webkit-box-shadow:inset 0px -5px 0px 0px #c7db40;
-moz-box-shadow:inset 0px -5px 0px 0px #C7DB40; -moz-box-shadow:inset 0px -5px 0px 0px #c7db40;
box-shadow:inset 0px -5px 0px 0px #C7DB40 box-shadow:inset 0px -5px 0px 0px #c7db40
} }
.navbar-fixed-top{ .navbar-fixed-top{
@ -1131,7 +1221,7 @@ fieldset[disabled] .navbar-default .btn-link:focus{
pre{ pre{
color:#000; color:#000;
background-color:#F5F5F5; background-color:#f5f5f5;
border-color:#ccc border-color:#ccc
} }
@ -1161,7 +1251,7 @@ browser.css
#fileBrowserDialog ul li a:hover{ #fileBrowserDialog ul li a:hover{
color:#00f; color:#00f;
background: rgb(220, 220, 220) none background:rgb(220, 220, 220) none
} }
.ui-menu .ui-menu-item{ .ui-menu .ui-menu-item{
@ -1200,7 +1290,7 @@ div.stepsguide .disabledstep p{
} }
#newShowPortal #addShowForm .stepsguide .disabledstep:hover > .smalltext{ #newShowPortal #addShowForm .stepsguide .disabledstep:hover > .smalltext{
color:#8a775e; color:#8a775e
} }
.stepDiv #searchResults div .exists-db{ .stepDiv #searchResults div .exists-db{
@ -1243,18 +1333,18 @@ tablesorter.css
} }
.tablesorter .tablesorter-header{ .tablesorter .tablesorter-header{
background:#333 url(data:image/gif;base64,R0lGODlhFQAJAIAAAP///////yH5BAEAAAEALAAAAAAVAAkAAAIXjI+AywnaYnhUMoqt3gZXPmVg94yJVQAAOw==) no-repeat center right; background:#333 url("data:image/gif;base64,R0lGODlhFQAJAIAAAP///////yH5BAEAAAEALAAAAAAVAAkAAAIXjI+AywnaYnhUMoqt3gZXPmVg94yJVQAAOw==") no-repeat center right;
/* background-image:url(../images/tablesorter/bg.gif) */ /* background-image:url("../images/tablesorter/bg.gif" */
} }
.tablesorter thead .tablesorter-headerDesc{ .tablesorter thead .tablesorter-headerDesc{
background:#555 url(data:image/gif;base64,R0lGODlhFQAEAIAAAP///////yH5BAEAAAEALAAAAAAVAAQAAAINjB+gC+jP2ptn0WskLQA7) no-repeat center right; background:#555 url("data:image/gif;base64,R0lGODlhFQAEAIAAAP///////yH5BAEAAAEALAAAAAAVAAQAAAINjB+gC+jP2ptn0WskLQA7") no-repeat center right;
/* background-image:url(../images/tablesorter/asc.gif) */ /* background-image:url("../images/tablesorter/asc.gif" */
} }
.tablesorter thead .tablesorter-headerAsc{ .tablesorter thead .tablesorter-headerAsc{
background:#555 url(data:image/gif;base64,R0lGODlhFQAEAIAAAP///////yH5BAEAAAEALAAAAAAVAAQAAAINjI8Bya2wnINUMopZAQA7) no-repeat center right; background:#555 url("data:image/gif;base64,R0lGODlhFQAEAIAAAP///////yH5BAEAAAEALAAAAAAVAAQAAAINjI8Bya2wnINUMopZAQA7") no-repeat center right;
/* background-image:url(../images/tablesorter/desc.gif) */ /* background-image:url("../images/tablesorter/desc.gif" */
} }
thead.tablesorter-stickyHeader{ thead.tablesorter-stickyHeader{
@ -1263,10 +1353,12 @@ thead.tablesorter-stickyHeader{
} }
/* Zebra Widget - row alternating colors */ /* Zebra Widget - row alternating colors */
.ui-state-default.row-odd,
.tablesorter tr.odd, .sickbeardTable tr.odd{ .tablesorter tr.odd, .sickbeardTable tr.odd{
background-color:#f5f1e4 background-color:#f5f1e4
} }
.ui-state-default.row-even,
.tablesorter tr.even, .sickbeardTable tr.even{ .tablesorter tr.even, .sickbeardTable tr.even{
background-color:#dfdacf background-color:#dfdacf
} }
@ -1355,14 +1447,14 @@ jquery.confirm.css
========================================================================== */ ========================================================================== */
#confirmOverlay{ #confirmOverlay{
background:url('../images/bg.gif'); background:url("../images/bg.gif");
background:-moz-linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)) repeat-x rgba(0, 0, 0, 0.5); background:-moz-linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)) repeat-x rgba(0, 0, 0, 0.5);
background:-webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0.5))) repeat-x rgba(0, 0, 0, 0.5); background:-webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0.5))) repeat-x rgba(0, 0, 0, 0.5);
z-index:100000 z-index:100000
} }
#confirmBox{ #confirmBox{
background:#F5F1E4; background:#f5f1e4;
border:1px solid #111; border:1px solid #111;
box-shadow:0 0 12px 0 rgba(0, 0, 0, 0.175) box-shadow:0 0 12px 0 rgba(0, 0, 0, 0.175)
} }
@ -1392,17 +1484,17 @@ jquery.confirm.css
} }
#confirmBox .green{ #confirmBox .green{
background-color:#3F7636 background-color:#3f7636
} }
#confirmBox .green:hover{ #confirmBox .green:hover{
background-color:#48873E background-color:#48873e
} }
#confirmBox .red{ #confirmBox .red{
background-color:#8D2D2B background-color:#8d2d2b
} }
#confirmBox .red:hover{ #confirmBox .red:hover{
background-color:#A13331 background-color:#a13331
} }

File diff suppressed because it is too large Load diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 306 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 691 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 477 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 496 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 436 B

After

Width:  |  Height:  |  Size: 531 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 263 B

After

Width:  |  Height:  |  Size: 693 B

View file

@ -2,12 +2,14 @@
#from sickbeard import db #from sickbeard import db
#from sickbeard.helpers import anon_url #from sickbeard.helpers import anon_url
#import os.path #import os.path
<% def sg_var(varname, default=False): return getattr(sickbeard, varname, default) %>#slurp#
<% def sg_str(varname, default=''): return getattr(sickbeard, varname, default) %>#slurp#
## ##
#set global $title = 'Configuration' #set global $title = 'Configuration'
#set global $header = 'Configuration' #set global $header = 'Configuration'
#set global $sbPath = '..' #set global $sbPath = '..'
#set global $topmenu = 'config' #set global $topmenu = 'config'
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_top.tmpl') #include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_top.tmpl')
## ##
#if $varExists('header') #if $varExists('header')
<h1 class='header'>$header</h1> <h1 class='header'>$header</h1>
@ -20,23 +22,25 @@
<tr> <tr>
<td class="infoTableHeader">Version: </td> <td class="infoTableHeader">Version: </td>
<td class="infoTableCell"> <td class="infoTableCell">
BRANCH: #echo $sickbeard.BRANCH or 'UNKNOWN'# / COMMIT: #echo $sickbeard.CUR_COMMIT_HASH or 'UNKNOWN'#<br /> BRANCH: #echo $sg_str('BRANCH') or 'UNKNOWN'# / COMMIT: #echo $sg_str('CUR_COMMIT_HASH') or 'UNKNOWN'#<br />
<em class="red-text">This is BETA software</em><br /> <em class="red-text">This is BETA software</em><br />
#if not $sickbeard.VERSION_NOTIFY: #if not $sg_var('VERSION_NOTIFY'):
You don't have version checking turned on, see "Check software updates" in Config > General. You don't have version checking turned on, see "Check software updates" in Config > General.
#end if #end if
</td> </td>
</tr> </tr>
<tr><td class="infoTableHeader">Config file:</td><td class="infoTableCell">$sickbeard.CONFIG_FILE</td></tr> <tr><td class="infoTableHeader">Config file:</td><td class="infoTableCell">$sg_str('CONFIG_FILE')</td></tr>
<tr><td class="infoTableHeader">Database file:</td><td class="infoTableCell">$db.dbFilename()</td></tr> <tr><td class="infoTableHeader">Database file:</td><td class="infoTableCell">$db.dbFilename()</td></tr>
<tr><td class="infoTableHeader">Cache Dir:</td><td class="infoTableCell">$sickbeard.CACHE_DIR</td></tr> <tr><td class="infoTableHeader">Cache Dir:</td><td class="infoTableCell">$sg_str('CACHE_DIR')</td></tr>
<tr><td class="infoTableHeader">Arguments:</td><td class="infoTableCell"><%= (sickbeard.MY_ARGS, 'None used')[0 == len(sickbeard.MY_ARGS)] %></td></tr> <tr><td class="infoTableHeader">Arguments:</td><td class="infoTableCell">#echo $sg_var('MY_ARGS') or 'None used'#</td></tr>
<tr><td class="infoTableHeader">Web Root:</td><td class="infoTableCell">$sickbeard.WEB_ROOT</td></tr> <tr><td class="infoTableHeader">Web Root:</td><td class="infoTableCell">$sg_str('WEB_ROOT')</td></tr>
<tr><td class="infoTableHeader">Python Version:</td><td class="infoTableCell">$sys.version[:120]</td></tr> <tr><td class="infoTableHeader">Python Version:</td><td class="infoTableCell">$sys.version[:120]</td></tr>
<tr class="infoTableSeperator"><td class="infoTableHeader"><i class="icon16-sg"></i> Homepage</td><td class="infoTableCell"><a href="<%= anon_url('https://github.com/SickGear/SickGear/wiki') %>" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false;">https://github.com/SickGear/SickGear/wiki</a></td></tr> <tr class="infoTableSeperator"><td class="infoTableHeader"><i class="icon16-sg"></i> Homepage</td><td class="infoTableCell"><a href="<%= anon_url('https://github.com/SickGear/SickGear/wiki') %>" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false;">https://github.com/SickGear/SickGear/wiki</a></td></tr>
<tr><td class="infoTableHeader"><i class="icon16-github"></i> Source</td><td class="infoTableCell"><a href="<%= anon_url('https://github.com/SickGear/SickGear/') %>" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false;">https://github.com/SickGear/SickGear/</a></td></tr> <tr><td class="infoTableHeader"><i class="icon16-github"></i> Source</td><td class="infoTableCell"><a href="<%= anon_url('https://github.com/SickGear/SickGear/') %>" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false;">https://github.com/SickGear/SickGear/</a></td></tr>
<tr><td class="infoTableHeader"><i class="icon16-mirc"></i> Internet Relay Chat</td><td class="infoTableCell"><a href="irc://irc.freenode.net/#SickGear" rel="noreferrer"><i>#SickGear</i> on <i>irc.freenode.net</i></a></td></tr> <tr><td class="infoTableHeader"><i class="icon16-mirc"></i> Internet Relay Chat</td><td class="infoTableCell"><a href="irc://irc.freenode.net/#SickGear" rel="noreferrer"><i>#SickGear</i> on <i>irc.freenode.net</i></a></td></tr>
<tr class="infoTableSeperator"><td class="infoTableHeader">Powered by</td><td class="infoTableCell">Python, HTML5, jQuery, SQLite, TheTVDB, Trakt.tv, Fanart.tv, TMDb, GitHub</td></tr>
<tr><td class="infoTableHeader">&nbsp;</td><td class="infoTableHeader">This project uses the TMDb API but is not endorsed or certified by TMDb.</td></tr>
</table> </table>
</div> </div>
#include $os.path.join($sickbeard.PROG_DIR,'gui/slick/interfaces/default/inc_bottom.tmpl') #include $os.path.join($sg_str('PROG_DIR'),'gui/slick/interfaces/default/inc_bottom.tmpl')

View file

@ -10,6 +10,8 @@
#from sickbeard.helpers import anon_url #from sickbeard.helpers import anon_url
#from sickbeard.logger import reverseNames as file_logging_presets #from sickbeard.logger import reverseNames as file_logging_presets
#from sickbeard.helpers import maybe_plural #from sickbeard.helpers import maybe_plural
<% def sg_var(varname, default=False): return getattr(sickbeard, varname, default) %>#slurp#
<% def sg_str(varname, default=''): return getattr(sickbeard, varname, default) %>#slurp#
## ##
#set global $title = 'Config - General' #set global $title = 'Config - General'
#set global $header = 'General Configuration' #set global $header = 'General Configuration'
@ -17,7 +19,7 @@
#set global $topmenu = 'config' #set global $topmenu = 'config'
## ##
#import os.path #import os.path
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_top.tmpl') #include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_top.tmpl')
#if $varExists('header') #if $varExists('header')
<h1 class="header">$header</h1> <h1 class="header">$header</h1>
@ -29,8 +31,8 @@
#set $selected = ' selected="selected"' #set $selected = ' selected="selected"'
## ##
#set $indexer = 0 #set $indexer = 0
#if $sickbeard.INDEXER_DEFAULT #if $sg_var('INDEXER_DEFAULT')
#set $indexer = $sickbeard.INDEXER_DEFAULT #set $indexer = $sg_var('INDEXER_DEFAULT')
#end if #end if
<script type="text/javascript" src="$sbRoot/js/config.js?v=$sbPID"></script> <script type="text/javascript" src="$sbRoot/js/config.js?v=$sbPID"></script>
@ -62,7 +64,7 @@
<label for="launch_browser"> <label for="launch_browser">
<span class="component-title">Launch browser</span> <span class="component-title">Launch browser</span>
<span class="component-desc"> <span class="component-desc">
<input type="checkbox" name="launch_browser" id="launch_browser"#echo ('', $checked)[$sickbeard.LAUNCH_BROWSER]#> <input type="checkbox" name="launch_browser" id="launch_browser"#echo ('', $checked)[$sg_var('LAUNCH_BROWSER')]#>
<p>open the SickGear home page on startup</p> <p>open the SickGear home page on startup</p>
</span> </span>
</label> </label>
@ -72,8 +74,8 @@
<label for="update_shows_on_start"> <label for="update_shows_on_start">
<span class="component-title">Update shows on startup</span> <span class="component-title">Update shows on startup</span>
<span class="component-desc"> <span class="component-desc">
<input type="checkbox" name="update_shows_on_start" id="update_shows_on_start"#echo ('', $checked)[$sickbeard.UPDATE_SHOWS_ON_START]#> <input type="checkbox" name="update_shows_on_start" id="update_shows_on_start"#echo ('', $checked)[$sg_var('UPDATE_SHOWS_ON_START')]#>
<p>with show data; episode plot, images, air and end dates, etc. Disable for a quicker startup. Show data is scheduled to update during hour <span class="show_update_hour_value">$sickbeard.SHOW_UPDATE_HOUR</span></p> <p>with show data; episode plot, images, air and end dates, etc. Disable for a quicker startup. Show data is scheduled to update during hour <span class="show_update_hour_value">$sg_var('SHOW_UPDATE_HOUR', 3)</span></p>
</span> </span>
</label> </label>
</div> </div>
@ -82,7 +84,7 @@
<label for="show_update_hour"> <label for="show_update_hour">
<span class="component-title">Update shows during hour</span> <span class="component-title">Update shows during hour</span>
<span class="component-desc"> <span class="component-desc">
<input type="number" name="show_update_hour" id="show_update_hour" value="$sickbeard.SHOW_UPDATE_HOUR" class="form-control input-sm input75"> <input type="number" name="show_update_hour" id="show_update_hour" value="$sg_var('SHOW_UPDATE_HOUR', 3)" class="form-control input-sm input75">
<p>(0 ... 23) with show data; episode plot, images, air and end dates, etc.</p> <p>(0 ... 23) with show data; episode plot, images, air and end dates, etc.</p>
</span> </span>
</label> </label>
@ -92,11 +94,11 @@
<span class="component-title">Send to trash for actions</span> <span class="component-title">Send to trash for actions</span>
<span class="component-desc"> <span class="component-desc">
<label for="trash_remove_show" class="nextline-block"> <label for="trash_remove_show" class="nextline-block">
<input type="checkbox" name="trash_remove_show" id="trash_remove_show"#echo ('', $checked)[$sickbeard.TRASH_REMOVE_SHOW]#> <input type="checkbox" name="trash_remove_show" id="trash_remove_show"#echo ('', $checked)[$sg_var('TRASH_REMOVE_SHOW')]#>
<p>when using show "Remove" and delete files</p> <p>when using show "Remove" and delete files</p>
</label> </label>
<label for="trash_rotate_logs" class="nextline-block"> <label for="trash_rotate_logs" class="nextline-block">
<input type="checkbox" name="trash_rotate_logs" id="trash_rotate_logs"#echo ('', $checked)[$sickbeard.TRASH_ROTATE_LOGS]#> <input type="checkbox" name="trash_rotate_logs" id="trash_rotate_logs"#echo ('', $checked)[$sg_var('TRASH_ROTATE_LOGS')]#>
<p>on scheduled deletes of the oldest log files</p> <p>on scheduled deletes of the oldest log files</p>
</label> </label>
<div class="clear-left"><p>selected actions use trash (recycle bin) instead of the default permanent delete</p></div> <div class="clear-left"><p>selected actions use trash (recycle bin) instead of the default permanent delete</p></div>
@ -107,7 +109,7 @@
<label for="log_dir"> <label for="log_dir">
<span class="component-title">Log file folder location</span> <span class="component-title">Log file folder location</span>
<span class="component-desc"> <span class="component-desc">
<input type="text" name="log_dir" id="log_dir" value="$sickbeard.ACTUAL_LOG_DIR" class="form-control input-sm input350"> <input type="text" name="log_dir" id="log_dir" value="$sg_str('ACTUAL_LOG_DIR')" class="form-control input-sm input350">
</span> </span>
</label> </label>
</div> </div>
@ -119,7 +121,7 @@
<select id="indexer_default" name="indexer_default" class="form-control input-sm"> <select id="indexer_default" name="indexer_default" class="form-control input-sm">
<option value="0"#echo ('', $selected)[0 == $indexer]#>All Indexers</option> <option value="0"#echo ('', $selected)[0 == $indexer]#>All Indexers</option>
#for $indexer in $indexers #for $indexer in $indexers
<option value="$indexer"#echo ('', $selected)[$indexer == $sickbeard.INDEXER_DEFAULT]#>$sickbeard.indexerApi().indexers[$indexer]</option> <option value="$indexer"#echo ('', $selected)[$indexer == $sg_var('INDEXER_DEFAULT', 0)]#>$sickbeard.indexerApi().indexers[$indexer]</option>
#end for #end for
</select> </select>
<span>as the default selection when adding new shows</span> <span>as the default selection when adding new shows</span>
@ -131,7 +133,7 @@
<label for="indexer_timeout"> <label for="indexer_timeout">
<span class="component-title">Timeout show indexer at</span> <span class="component-title">Timeout show indexer at</span>
<span class="component-desc"> <span class="component-desc">
<input type="text" name="indexer_timeout" id="indexer_timeout" value="$sickbeard.INDEXER_TIMEOUT" class="form-control input-sm input75"> <input type="text" name="indexer_timeout" id="indexer_timeout" value="$sg_var('INDEXER_TIMEOUT', 20)" class="form-control input-sm input75">
<p>seconds of inactivity when finding new shows (default:10)</p> <p>seconds of inactivity when finding new shows (default:10)</p>
</span> </span>
</label> </label>
@ -142,7 +144,7 @@
<span class="component-title">Show root directories</span> <span class="component-title">Show root directories</span>
<span class="component-desc"> <span class="component-desc">
<p>where the files of shows are located</p> <p>where the files of shows are located</p>
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_rootDirs.tmpl') #include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_rootDirs.tmpl')
</span> </span>
</label> </label>
</div> </div>
@ -162,7 +164,7 @@
<label for="version_notify"> <label for="version_notify">
<span class="component-title">Check software updates</span> <span class="component-title">Check software updates</span>
<span class="component-desc"> <span class="component-desc">
<input type="checkbox" name="version_notify" id="version_notify"#echo ('', $checked)[$sickbeard.VERSION_NOTIFY]#> <input type="checkbox" name="version_notify" id="version_notify"#echo ('', $checked)[$sg_var('VERSION_NOTIFY', True)]#>
<p>and display notifications when updates are available. <p>and display notifications when updates are available.
Checks are run on startup and at the frequency set below*</p> Checks are run on startup and at the frequency set below*</p>
</span> </span>
@ -173,7 +175,7 @@
<label for="auto_update"> <label for="auto_update">
<span class="component-title">Automatically update</span> <span class="component-title">Automatically update</span>
<span class="component-desc"> <span class="component-desc">
<input type="checkbox" name="auto_update" id="auto_update"#echo ('', $checked)[$sickbeard.AUTO_UPDATE]#> <input type="checkbox" name="auto_update" id="auto_update"#echo ('', $checked)[$sg_var('AUTO_UPDATE')]#>
<p>fetch and install software updates. <p>fetch and install software updates.
Updates are run on startup and in the background at the frequency set below<sup>1</sup></p> Updates are run on startup and in the background at the frequency set below<sup>1</sup></p>
</span> </span>
@ -184,7 +186,7 @@
<label> <label>
<span class="component-title">Check the server every<sup>1</sup></span> <span class="component-title">Check the server every<sup>1</sup></span>
<span class="component-desc"> <span class="component-desc">
<input type="text" name="update_frequency" id="update_frequency" value="$sickbeard.UPDATE_FREQUENCY" class="form-control input-sm input75"> <input type="text" name="update_frequency" id="update_frequency" value="$sg_var('UPDATE_FREQUENCY', 12)" class="form-control input-sm input75">
<p>hours for software updates (default:12)</p> <p>hours for software updates (default:12)</p>
</span> </span>
</label> </label>
@ -194,7 +196,7 @@
<label for="notify_on_update"> <label for="notify_on_update">
<span class="component-title">Notify on software update</span> <span class="component-title">Notify on software update</span>
<span class="component-desc"> <span class="component-desc">
<input type="checkbox" name="notify_on_update" id="notify_on_update"#echo ('', $checked)[$sickbeard.NOTIFY_ON_UPDATE]#> <input type="checkbox" name="notify_on_update" id="notify_on_update"#echo ('', $checked)[$sg_var('NOTIFY_ON_UPDATE')]#>
<p>send a message to all enabled notifiers when SickGear has been updated</p> <p>send a message to all enabled notifiers when SickGear has been updated</p>
</span> </span>
</label> </label>
@ -222,8 +224,8 @@
<span class="component-title">Display theme:</span> <span class="component-title">Display theme:</span>
<span class="component-desc"> <span class="component-desc">
<select id="theme_name" name="theme_name" class="form-control input-sm"> <select id="theme_name" name="theme_name" class="form-control input-sm">
<option value="dark"#echo ('', $selected)['dark' == $sickbeard.THEME_NAME]#>Dark</option> <option value="dark"#echo ('', $selected)['dark' == $sg_str('THEME_NAME', 'dark')]#>Dark</option>
<option value="light"#echo ('', $selected)['light' == $sickbeard.THEME_NAME]#>Light</option> <option value="light"#echo ('', $selected)['light' == $sg_str('THEME_NAME')]#>Light</option>
</select> </select>
<span class="red-text">for appearance to take effect, save then refresh your browser</span> <span class="red-text">for appearance to take effect, save then refresh your browser</span>
</span> </span>
@ -235,32 +237,43 @@
<span class="component-title">Use as default home page:</span> <span class="component-title">Use as default home page:</span>
<span class="component-desc"> <span class="component-desc">
<select id="default_home" name="default_home" class="form-control input-sm"> <select id="default_home" name="default_home" class="form-control input-sm">
<option value="shows"#echo ('', $selected)['shows' == $sickbeard.DEFAULT_HOME]#>Shows</option> <option value="shows"#echo ('', $selected)['shows' == $sg_str('DEFAULT_HOME')]#>Shows</option>
<option value="episodes"#echo ('', $selected)['episodes' == $sickbeard.DEFAULT_HOME]#>Episodes</option> <option value="episodes"#echo ('', $selected)['episodes' == $sg_str('DEFAULT_HOME')]#>Episodes</option>
<option value="history"#echo ('', $selected)['history' == $sickbeard.DEFAULT_HOME]#>History</option> <option value="history"#echo ('', $selected)['history' == $sg_str('DEFAULT_HOME')]#>History</option>
</select> </select>
</span> </span>
</label> </label>
</div> </div>
#if not hasattr($sickbeard, 'FANART_LIMIT')#<span class="red-text">Restart SickGear to reveal new options here</span>#else#
<div class="field-pair">
<label for="fanart_limit">
<span class="component-title">Maximum fanart image files</span>
<span class="component-desc">
<input type="text" name="fanart_limit" id="fanart_limit" value="$sg_var('FANART_LIMIT', 3)" class="form-control input-sm input75">
<span>per show to cache (0 ... 500)</span>
</span>
</label>
</div>
#end if
<div class="field-pair"> <div class="field-pair">
<label for="showlist_tagview"> <label for="showlist_tagview">
<span class="component-title">Group show list shows into:</span> <span class="component-title">Group show list shows into:</span>
<span class="component-desc"> <span class="component-desc">
<select id="showlist_tagview" name="showlist_tagview" class="form-control input-sm"> <select id="showlist_tagview" name="showlist_tagview" class="form-control input-sm">
<option value="standard"#echo ('', $selected)['standard' == $sickbeard.SHOWLIST_TAGVIEW]#>One Show List</option> <option value="standard"#echo ('', $selected)['standard' == $sg_str('SHOWLIST_TAGVIEW', 'standard')]#>One Show List</option>
<option value="anime"#echo ('', $selected)['anime' == $sickbeard.SHOWLIST_TAGVIEW]#>Show / Anime Lists</option> <option value="anime"#echo ('', $selected)['anime' == $sg_str('SHOWLIST_TAGVIEW')]#>Show / Anime Lists</option>
<option value="custom"#echo ('', $selected)['custom' == $sickbeard.SHOWLIST_TAGVIEW]#>Custom Lists</option> <option value="custom"#echo ('', $selected)['custom' == $sg_str('SHOWLIST_TAGVIEW')]#>Custom Lists</option>
</select> </select>
#set $hidden = ' class="hidden"' #set $hidden = ' class="hidden"'
<span id="showlist_tagview_standard"#echo ('', $hidden)['standard' not in $sickbeard.SHOWLIST_TAGVIEW]#>that contains all shows (default)</span> <span id="showlist_tagview_standard"#echo ('', $hidden)['standard' not in $sg_str('SHOWLIST_TAGVIEW', 'standard')]#>that contains all shows (default)</span>
<span id="showlist_tagview_anime"#echo ('', $hidden)['anime' not in $sickbeard.SHOWLIST_TAGVIEW]#>two groups, the show list and anime</span> <span id="showlist_tagview_anime"#echo ('', $hidden)['anime' not in $sg_str('SHOWLIST_TAGVIEW')]#>two groups, the show list and anime</span>
<span id="showlist_tagview_custom"#echo ('', $hidden)['custom' not in $sickbeard.SHOWLIST_TAGVIEW]#>multiple custom<sup>1</sup> named groups and a "Show List"</span> <span id="showlist_tagview_custom"#echo ('', $hidden)['custom' not in $sg_str('SHOWLIST_TAGVIEW')]#>multiple custom<sup>1</sup> named groups and a "Show List"</span>
</span> </span>
</label> </label>
</div> </div>
<div id="showlist_tagview_custom_config" class="field-pair#if $sickbeard.SHOWLIST_TAGVIEW != 'custom' then ' hidden' else ''#"> <div id="showlist_tagview_custom_config" class="field-pair#if $sg_str('SHOWLIST_TAGVIEW') != 'custom' then ' hidden' else ''#">
<label for="show_tags"> <label for="show_tags">
<span class="component-title">Group names for show list<sup>1</sup></span> <span class="component-title">Group names for show list<sup>1</sup></span>
<span class="component-desc"> <span class="component-desc">
@ -275,7 +288,7 @@
<label for="home_search_focus"> <label for="home_search_focus">
<span class="component-title">Give show list search focus</span> <span class="component-title">Give show list search focus</span>
<span class="component-desc"> <span class="component-desc">
<input type="checkbox" name="home_search_focus" id="home_search_focus"#echo ('', $checked)[$sickbeard.HOME_SEARCH_FOCUS]#> <input type="checkbox" name="home_search_focus" id="home_search_focus"#echo ('', $checked)[$sg_var('HOME_SEARCH_FOCUS', True)]#>
<p>page refresh on "Show List" will start search box focused</p> <p>page refresh on "Show List" will start search box focused</p>
</span> </span>
</label> </label>
@ -285,7 +298,7 @@
<label for="use_imdb_info"> <label for="use_imdb_info">
<span class="component-title">Enable IMDb info</span> <span class="component-title">Enable IMDb info</span>
<span class="component-desc"> <span class="component-desc">
<input type="checkbox" name="use_imdb_info" id="use_imdb_info"#echo ('', $checked)[$sickbeard.USE_IMDB_INFO]#> <input type="checkbox" name="use_imdb_info" id="use_imdb_info"#echo ('', $checked)[$sg_var('USE_IMDB_INFO', True)]#>
<p>for ui links, display show; ratings, country flag, year, runtime, and genre tags</p> <p>for ui links, display show; ratings, country flag, year, runtime, and genre tags</p>
</span> </span>
</label> </label>
@ -298,7 +311,7 @@
<span class="component-desc"> <span class="component-desc">
<select id="imdb-accounts" class="pull-left form-control input-sm"> <select id="imdb-accounts" class="pull-left form-control input-sm">
<option value="new" selected="selected">Add watchlist ...</option> <option value="new" selected="selected">Add watchlist ...</option>
#for $i, $v in $enumerate($sickbeard.IMDB_ACCOUNTS) #for $i, $v in $enumerate($sg_str('IMDB_ACCOUNTS'))
#if not $i % 2 #if not $i % 2
#set $id = $v #set $id = $v
#else #else
@ -326,7 +339,7 @@
<label for="sort_article"> <label for="sort_article">
<span class="component-title">Sort with "The", "A", "An"</span> <span class="component-title">Sort with "The", "A", "An"</span>
<span class="component-desc"> <span class="component-desc">
<input type="checkbox" name="sort_article" id="sort_article"#echo ('', $checked)[$sickbeard.SORT_ARTICLE]#> <input type="checkbox" name="sort_article" id="sort_article"#echo ('', $checked)[$sg_var('SORT_ARTICLE')]#>
<p>include articles ("The", "A", "An") when sorting show lists</p> <p>include articles ("The", "A", "An") when sorting show lists</p>
</span> </span>
</label> </label>
@ -340,16 +353,16 @@
<label for="fuzzy_dating"> <label for="fuzzy_dating">
<span class="component-title">Display fuzzy dates</span> <span class="component-title">Display fuzzy dates</span>
<span class="component-desc"> <span class="component-desc">
<input type="checkbox" name="fuzzy_dating" id="fuzzy_dating" class="viewIf datePresets"#echo ('', $checked)[$sickbeard.FUZZY_DATING == True]#> <input type="checkbox" name="fuzzy_dating" id="fuzzy_dating" class="viewIf datePresets"#echo ('', $checked)[$sg_var('FUZZY_DATING') == True]#>
<p>move absolute dates into tooltips and display e.g. "Last Thu", "On Tue"</p> <p>move absolute dates into tooltips and display e.g. "Last Thu", "On Tue"</p>
</span> </span>
</label> </label>
</div> </div>
<div class="field-pair show_if_fuzzy_dating#echo (' metadataDiv', '')[$sickbeard.FUZZY_DATING]#"> <div class="field-pair show_if_fuzzy_dating#echo (' metadataDiv', '')[$sg_var('FUZZY_DATING')]#">
<label for="trim_zero"> <label for="trim_zero">
<span class="component-title">Trim date and time</span> <span class="component-title">Trim date and time</span>
<span class="component-desc"> <span class="component-desc">
<input type="checkbox" name="trim_zero" id="trim_zero"#echo ('', $checked)[True == $sickbeard.TRIM_ZERO]#> <input type="checkbox" name="trim_zero" id="trim_zero"#echo ('', $checked)[True == $sg_var('TRIM_ZERO')]#>
<p>display minimalist date and time i.e. <del>02:00</del> = 2:00, <del>02:00pm</del> = 2pm, <del>03 Jan</del> = 3 Jan</p> <p>display minimalist date and time i.e. <del>02:00</del> = 2:00, <del>02:00pm</del> = 2pm, <del>03 Jan</del> = 3 Jan</p>
</span> </span>
</label> </label>
@ -359,16 +372,16 @@
<label for="date_presets"> <label for="date_presets">
<span class="component-title">Date style:</span> <span class="component-title">Date style:</span>
<span class="component-desc"> <span class="component-desc">
<select class="form-control input-sm#echo (' metadataDiv', '')[$sickbeard.FUZZY_DATING]#" id="date_presets#echo ('_na', '')[$sickbeard.FUZZY_DATING]#" name="date_preset#echo ('_na', '')[$sickbeard.FUZZY_DATING]#"> <select class="form-control input-sm#echo (' metadataDiv', '')[$sg_var('FUZZY_DATING')]#" id="date_presets#echo ('_na', '')[$sg_var('FUZZY_DATING')]#" name="date_preset#echo ('_na', '')[$sg_var('FUZZY_DATING')]#">
#for $cur_preset in $date_presets #for $cur_preset in $date_presets
<option value="$cur_preset" #echo ('', $selected)[$cur_preset == $sickbeard.DATE_PRESET or ('%x' == $sickbeard.DATE_PRESET and '$cur_preset' == '%a, %b %d, %Y')]#>$datetime.datetime($datetime.datetime.now().year, 12, 31, 14, 30, 47).strftime($cur_preset)</option> <option value="$cur_preset" #echo ('', $selected)[$cur_preset == $sg_str('DATE_PRESET', '%x') or ('%x' == $sg_str('DATE_PRESET', '%x') and '$cur_preset' == '%a, %b %d, %Y')]#>$datetime.datetime($datetime.datetime.now().year, 12, 31, 14, 30, 47).strftime($cur_preset)</option>
#end for #end for
</select> </select>
<select class="form-control input-sm#echo ('', ' metadataDiv')[$sickbeard.FUZZY_DATING]#" id="date_presets#echo ('', '_na')[$sickbeard.FUZZY_DATING]#" name="date_preset#echo ('', '_na')[$sickbeard.FUZZY_DATING]#"> <select class="form-control input-sm#echo ('', ' metadataDiv')[$sg_var('FUZZY_DATING')]#" id="date_presets#echo ('', '_na')[$sg_var('FUZZY_DATING')]#" name="date_preset#echo ('', '_na')[$sg_var('FUZZY_DATING')]#">
<option value="%x"#echo ('', $selected)['%x' == $sickbeard.DATE_PRESET]#>Use System Default</option> <option value="%x"#echo ('', $selected)['%x' == $sg_str('DATE_PRESET', '%x')]#>Use System Default</option>
#for $cur_preset in $date_presets #for $cur_preset in $date_presets
<option value="$cur_preset"#echo ('', $selected)[$cur_preset == $sickbeard.DATE_PRESET]#>$datetime.datetime($datetime.datetime.now().year, 12, 31, 14, 30, 47).strftime($cur_preset)</option> <option value="$cur_preset"#echo ('', $selected)[$cur_preset == $sg_str('DATE_PRESET', '%x')]#>$datetime.datetime($datetime.datetime.now().year, 12, 31, 14, 30, 47).strftime($cur_preset)</option>
#end for #end for
</select> </select>
</span> </span>
@ -381,8 +394,8 @@
<span class="component-desc"> <span class="component-desc">
<select id="time_presets" name="time_preset" class="form-control input-sm"> <select id="time_presets" name="time_preset" class="form-control input-sm">
#for $cur_preset in $time_presets #for $cur_preset in $time_presets
#set $show_seconds = not $sickbeard.FUZZY_DATING #set $show_seconds = not $sg_var('FUZZY_DATING')
<option value="$cur_preset"#echo ('', $selected)[$cur_preset == $sickbeard.TIME_PRESET_W_SECONDS]#>$sbdatetime.now().sbftime(show_seconds=$show_seconds, t_preset=$cur_preset)</option> <option value="$cur_preset"#echo ('', $selected)[$cur_preset == $sg_str('TIME_PRESET_W_SECONDS', '%I:%M:%S %p')]#>$sbdatetime.now().sbftime(show_seconds=$show_seconds, t_preset=$cur_preset)</option>
#end for #end for
</select> </select>
<span id="trim_info_seconds"><b>note:</b> seconds are only shown on the History page</span> <span id="trim_info_seconds"><b>note:</b> seconds are only shown on the History page</span>
@ -394,10 +407,10 @@
<span class="component-title">Timezone:</span> <span class="component-title">Timezone:</span>
<span class="component-desc"> <span class="component-desc">
<label for="local" class="space-right"> <label for="local" class="space-right">
<input type="radio" name="timezone_display" id="local" value="local"#echo ('', $checked)['local' == $sickbeard.TIMEZONE_DISPLAY]#>local <input type="radio" name="timezone_display" id="local" value="local"#echo ('', $checked)['local' == $sg_str('TIMEZONE_DISPLAY')]#>local
</label> </label>
<label for="network"> <label for="network">
<input type="radio" name="timezone_display" id="network" value="network"#echo ('', $checked)['network' == $sickbeard.TIMEZONE_DISPLAY]#>network <input type="radio" name="timezone_display" id="network" value="network"#echo ('', $checked)['network' == $sg_str('TIMEZONE_DISPLAY', 'network')]#>network
</label> </label>
<div class="clear-left"><p>display dates and times in either your timezone or the shows network timezone</p></div> <div class="clear-left"><p>display dates and times in either your timezone or the shows network timezone</p></div>
</span> </span>
@ -423,7 +436,7 @@
<label for="web_username"> <label for="web_username">
<span class="component-title">Username</span> <span class="component-title">Username</span>
<span class="component-desc"> <span class="component-desc">
<input type="text" name="web_username" id="web_username" value="$sickbeard.WEB_USERNAME" class="form-control input-sm input300"> <input type="text" name="web_username" id="web_username" value="$sg_str('WEB_USERNAME')" class="form-control input-sm input300">
<p>blank for none</p> <p>blank for none</p>
</span> </span>
</label> </label>
@ -433,7 +446,7 @@
<label for="web_password"> <label for="web_password">
<span class="component-title">Password</span> <span class="component-title">Password</span>
<span class="component-desc"> <span class="component-desc">
<input type="password" autocomplete="nope" name="web_password" id="web_password" value="#echo '*' * len($sickbeard.WEB_PASSWORD)#" class="form-control input-sm input300"> <input type="password" autocomplete="nope" name="web_password" id="web_password" value="#echo '*' * len($sg_str('WEB_PASSWORD'))#" class="form-control input-sm input300">
<p>blank for none</p> <p>blank for none</p>
<span class="clear-left">check autoProcessTV.cfg is set up for external apps to use post processing scripts</span> <span class="clear-left">check autoProcessTV.cfg is set up for external apps to use post processing scripts</span>
</span> </span>
@ -444,7 +457,7 @@
<label for="calendar_unprotected"> <label for="calendar_unprotected">
<span class="component-title">Unprotected calendar</span> <span class="component-title">Unprotected calendar</span>
<span class="component-desc"> <span class="component-desc">
<input type="checkbox" name="calendar_unprotected" id="calendar_unprotected"#echo ('', $checked)[$sickbeard.CALENDAR_UNPROTECTED]#> <input type="checkbox" name="calendar_unprotected" id="calendar_unprotected"#echo ('', $checked)[$sg_var('CALENDAR_UNPROTECTED')]#>
<p>permit subscribing to the calendar without username and password. <p>permit subscribing to the calendar without username and password.
Some services like Google Calendar will only work with <b class="boldest">no</b> authentication</p> Some services like Google Calendar will only work with <b class="boldest">no</b> authentication</p>
</span> </span>
@ -456,7 +469,7 @@
<label for="use_api"> <label for="use_api">
<span class="component-title">API enable</span> <span class="component-title">API enable</span>
<span class="component-desc"> <span class="component-desc">
<input type="checkbox" name="use_api" class="enabler" id="use_api"#echo ('', $checked)[$sickbeard.USE_API]#> <input type="checkbox" name="use_api" class="enabler" id="use_api"#echo ('', $checked)[$sg_var('USE_API')]#>
<p>permit the use of the SickGear (SickBeard) API</p> <p>permit the use of the SickGear (SickBeard) API</p>
</span> </span>
</label> </label>
@ -466,7 +479,7 @@
<label for="api_key"> <label for="api_key">
<span class="component-title">API key</span> <span class="component-title">API key</span>
<span class="component-desc"> <span class="component-desc">
<input type="text" name="api_key" id="api_key" value="$sickbeard.API_KEY" class="form-control input-sm input300" readonly="readonly"> <input type="text" name="api_key" id="api_key" value="$sg_str('API_KEY')" class="form-control input-sm input300" readonly="readonly">
<input class="btn btn-inline" type="button" id="generate_new_apikey" value="Generate"> <input class="btn btn-inline" type="button" id="generate_new_apikey" value="Generate">
<div class="clear-left"><p>used to give 3rd party programs limited access to SickGear</p></div> <div class="clear-left"><p>used to give 3rd party programs limited access to SickGear</p></div>
</span> </span>
@ -478,7 +491,7 @@
<label for="web_port"> <label for="web_port">
<span class="component-title">HTTP port</span> <span class="component-title">HTTP port</span>
<span class="component-desc"> <span class="component-desc">
<input type="text" name="web_port" id="web_port" value="$sickbeard.WEB_PORT" class="form-control input-sm input100"> <input type="text" name="web_port" id="web_port" value="$sg_var('WEB_PORT', 8081)" class="form-control input-sm input100">
<p>web port to access and browse SickGear (default:8081)</p> <p>web port to access and browse SickGear (default:8081)</p>
</span> </span>
</label> </label>
@ -488,7 +501,7 @@
<label for="web_log"> <label for="web_log">
<span class="component-title">HTTP logs</span> <span class="component-title">HTTP logs</span>
<span class="component-desc"> <span class="component-desc">
<input type="checkbox" name="web_log" id="web_log"#echo ('', $checked)[$sickbeard.WEB_LOG]#> <input type="checkbox" name="web_log" id="web_log"#echo ('', $checked)[$sg_var('WEB_LOG')]#>
<p>enable logs from the internal web server</p> <p>enable logs from the internal web server</p>
</span> </span>
</label> </label>
@ -498,7 +511,7 @@
<label for="enable_https"> <label for="enable_https">
<span class="component-title">SSL enable</span> <span class="component-title">SSL enable</span>
<span class="component-desc"> <span class="component-desc">
<input type="checkbox" name="enable_https" class="enabler" id="enable_https"#echo ('', $checked)[$sickbeard.ENABLE_HTTPS]#> <input type="checkbox" name="enable_https" class="enabler" id="enable_https"#echo ('', $checked)[$sg_var('ENABLE_HTTPS')]#>
<p>use a HTTPS address to access the web interface</p> <p>use a HTTPS address to access the web interface</p>
</span> </span>
</label> </label>
@ -508,7 +521,7 @@
<label for="https_cert"> <label for="https_cert">
<span class="component-title">HTTPS certificate</span> <span class="component-title">HTTPS certificate</span>
<span class="component-desc"> <span class="component-desc">
<input type="text" name="https_cert" id="https_cert" value="$sickbeard.HTTPS_CERT" class="form-control input-sm input300"> <input type="text" name="https_cert" id="https_cert" value="$sg_str('HTTPS_CERT')" class="form-control input-sm input300">
<div class="clear-left"><p>file name or path to a <b class="boldest">server.crt</b> certificate file</p></div> <div class="clear-left"><p>file name or path to a <b class="boldest">server.crt</b> certificate file</p></div>
</span> </span>
</label> </label>
@ -517,7 +530,7 @@
<label for="https_key"> <label for="https_key">
<span class="component-title">HTTPS key</span> <span class="component-title">HTTPS key</span>
<span class="component-desc"> <span class="component-desc">
<input type="text" name="https_key" id="https_key" value="$sickbeard.HTTPS_KEY" class="form-control input-sm input300"> <input type="text" name="https_key" id="https_key" value="$sg_str('HTTPS_KEY')" class="form-control input-sm input300">
<div class="clear-left"><p>file name or path to a <b class="boldest">server.key</b> file</p></div> <div class="clear-left"><p>file name or path to a <b class="boldest">server.key</b> file</p></div>
</span> </span>
</label> </label>
@ -528,7 +541,7 @@
<label for="web_ipv6"> <label for="web_ipv6">
<span class="component-title">Listen on IPv6</span> <span class="component-title">Listen on IPv6</span>
<span class="component-desc"> <span class="component-desc">
<input type="checkbox" name="web_ipv6" id="web_ipv6"#echo ('', $checked)[$sickbeard.WEB_IPV6]#> <input type="checkbox" name="web_ipv6" id="web_ipv6"#echo ('', $checked)[$sg_var('WEB_IPV6')]#>
<p>attempt binding to any available IPv6 address</p> <p>attempt binding to any available IPv6 address</p>
</span> </span>
</label> </label>
@ -538,7 +551,7 @@
<label for="handle_reverse_proxy"> <label for="handle_reverse_proxy">
<span class="component-title">Reverse proxy headers</span> <span class="component-title">Reverse proxy headers</span>
<span class="component-desc"> <span class="component-desc">
<input type="checkbox" name="handle_reverse_proxy" id="handle_reverse_proxy"#echo ('', $checked)[$sickbeard.HANDLE_REVERSE_PROXY]#> <input type="checkbox" name="handle_reverse_proxy" id="handle_reverse_proxy"#echo ('', $checked)[$sg_var('HANDLE_REVERSE_PROXY')]#>
<p>accept the following reverse proxy headers (advanced)...<br />(X-Forwarded-For, X-Forwarded-Host, and X-Forwarded-Proto)</p> <p>accept the following reverse proxy headers (advanced)...<br />(X-Forwarded-For, X-Forwarded-Host, and X-Forwarded-Proto)</p>
</span> </span>
</label> </label>
@ -574,7 +587,7 @@
</label> </label>
</div> </div>
#if $sickbeard.BRANCH != 'master' #if $sg_str('BRANCH', 'master') != 'master'
<div class="field-pair"> <div class="field-pair">
<label> <label>
<span class="component-title">Pull request:</span> <span class="component-title">Pull request:</span>
@ -593,7 +606,7 @@
<label for="git_remote"> <label for="git_remote">
<span class="component-title">Git remote for branch</span> <span class="component-title">Git remote for branch</span>
<span class="component-desc"> <span class="component-desc">
<input type="text" name="git_remote" id="git_remote" value="$sickbeard.GIT_REMOTE" class="form-control input-sm input300"> <input type="text" name="git_remote" id="git_remote" value="$sg_str('GIT_REMOTE')" class="form-control input-sm input300">
<div class="clear-left"><p>default:origin. Access repo configured remotes (save then refresh browser)</p></div> <div class="clear-left"><p>default:origin. Access repo configured remotes (save then refresh browser)</p></div>
</span> </span>
</label> </label>
@ -603,7 +616,7 @@
<label> <label>
<span class="component-title">Git executable path</span> <span class="component-title">Git executable path</span>
<span class="component-desc"> <span class="component-desc">
<input type="text" name="git_path" value="$sickbeard.GIT_PATH" class="form-control input-sm input300"> <input type="text" name="git_path" value="$sg_str('GIT_PATH')" class="form-control input-sm input300">
<div class="clear-left"><p>only needed if OS is unable to locate git from env</p></div> <div class="clear-left"><p>only needed if OS is unable to locate git from env</p></div>
</span> </span>
</label> </label>
@ -615,7 +628,7 @@
<span class="component-desc"> <span class="component-desc">
<select id="cpu_presets" name="cpu_preset" class="form-control input-sm"> <select id="cpu_presets" name="cpu_preset" class="form-control input-sm">
#for $cur_preset in $sorted($cpu_presets.items(), key=$operator.itemgetter(1), reverse=True) #for $cur_preset in $sorted($cpu_presets.items(), key=$operator.itemgetter(1), reverse=True)
<option value="$cur_preset[0]"#echo ('', $selected)[$cur_preset[0] == $sickbeard.CPU_PRESET]#>$cur_preset[0].capitalize()</option> <option value="$cur_preset[0]"#echo ('', $selected)[$cur_preset[0] == $sg_str('CPU_PRESET', 'DISABLED')]#>$cur_preset[0].capitalize()</option>
#end for #end for
</select> </select>
<span>Disabled (default). High is lower and Low is higher CPU use</span> <span>Disabled (default). High is lower and Low is higher CPU use</span>
@ -627,7 +640,7 @@
<label> <label>
<span class="component-title">Anonymous redirect</span> <span class="component-title">Anonymous redirect</span>
<span class="component-desc"> <span class="component-desc">
<input type="text" name="anon_redirect" value="$sickbeard.ANON_REDIRECT" class="form-control input-sm input300"> <input type="text" name="anon_redirect" value="$sg_str('ANON_REDIRECT')" class="form-control input-sm input300">
<div class="clear-left"><p>backlink protection via anonymizer service, must end in "?"</p></div> <div class="clear-left"><p>backlink protection via anonymizer service, must end in "?"</p></div>
</span> </span>
</label> </label>
@ -637,7 +650,7 @@
<label for="encryption_version"> <label for="encryption_version">
<span class="component-title">Encrypt passwords</span> <span class="component-title">Encrypt passwords</span>
<span class="component-desc"> <span class="component-desc">
<input type="checkbox" name="encryption_version" id="encryption_version"#echo ('', $checked)[$sickbeard.ENCRYPTION_VERSION]#> <input type="checkbox" name="encryption_version" id="encryption_version"#echo ('', $checked)[$sg_var('ENCRYPTION_VERSION')]#>
<p>in the <code>config.ini</code> file. <p>in the <code>config.ini</code> file.
<b>Warning:</b> Passwords must only contain <a target="_blank" href="<%= anon_url('http://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters') %>">ASCII characters</a></p> <b>Warning:</b> Passwords must only contain <a target="_blank" href="<%= anon_url('http://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters') %>">ASCII characters</a></p>
</span> </span>
@ -648,7 +661,7 @@
<label> <label>
<span class="component-title">Proxy host</span> <span class="component-title">Proxy host</span>
<span class="component-desc"> <span class="component-desc">
<input type="text" name="proxy_setting" value="$sickbeard.PROXY_SETTING" class="form-control input-sm input300"> <input type="text" name="proxy_setting" value="$sg_str('PROXY_SETTING')" class="form-control input-sm input300">
<p>blank to disable</p> <p>blank to disable</p>
<div class="clear-left"><p>proxy address for connecting to providers (use 'PAC:Url' for PAC support)</p></div> <div class="clear-left"><p>proxy address for connecting to providers (use 'PAC:Url' for PAC support)</p></div>
</span> </span>
@ -659,7 +672,7 @@
<label for="proxy_indexers"> <label for="proxy_indexers">
<span class="component-title">Use proxy for indexers</span> <span class="component-title">Use proxy for indexers</span>
<span class="component-desc"> <span class="component-desc">
<input type="checkbox" name="proxy_indexers" id="proxy_indexers"#echo ('', $checked)[True == $sickbeard.PROXY_INDEXERS]#> <input type="checkbox" name="proxy_indexers" id="proxy_indexers"#echo ('', $checked)[True == $sg_var('PROXY_INDEXERS')]#>
<p>use proxy host for TV info source connections</p> <p>use proxy host for TV info source connections</p>
</span> </span>
</label> </label>
@ -677,7 +690,7 @@
#set $level_title = $level.title().upper() #set $level_title = $level.title().upper()
#set $level_count -= 1 #set $level_count -= 1
#set $level_text = '%s%s' % ($level.title(), (('', ' only')[0 == $level_count], ' and the next%s level%s' % ((' ' + str($level_count), '')[1 == $level_count], maybe_plural($level_count)))[0 < $level_count]) #set $level_text = '%s%s' % ($level.title(), (('', ' only')[0 == $level_count], ' and the next%s level%s' % ((' ' + str($level_count), '')[1 == $level_count], maybe_plural($level_count)))[0 < $level_count])
<option value="$level_title"#echo ('', $selected)[$level_title == $sickbeard.FILE_LOGGING_PRESET]#>$level_text</option> <option value="$level_title"#echo ('', $selected)[$level_title == $sg_str('FILE_LOGGING_PRESET', 'DB')]#>$level_text</option>
#end for #end for
</select> </select>
<span>(default: Db)</span> <span>(default: Db)</span>
@ -691,7 +704,7 @@
</div><!-- /component-group3 //--> </div><!-- /component-group3 //-->
<br/> <br/>
<h6 class="pull-right"><b>All non-absolute folder locations are relative to <span class="path">$sickbeard.DATA_DIR</span></b></h6> <h6 class="pull-right"><b>All non-absolute folder locations are relative to <span class="path">$sg_str('DATA_DIR')</span></b></h6>
<input type="submit" class="btn pull-left config_submitter button" value="Save Changes"> <input type="submit" class="btn pull-left config_submitter button" value="Save Changes">
</div><!-- /config-components --> </div><!-- /config-components -->
@ -709,4 +722,4 @@
//--> //-->
</script> </script>
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_bottom.tmpl') #include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_bottom.tmpl')

View file

@ -104,17 +104,21 @@
$x.providerType == $GenericProvider.TORRENT and $sickbeard.USE_TORRENTS] $x.providerType == $GenericProvider.TORRENT and $sickbeard.USE_TORRENTS]
#set $cur_name = $cur_provider.get_id() #set $cur_name = $cur_provider.get_id()
#set $cur_url = $cur_provider.url #set $cur_url = $cur_provider.url
#set $show_type = $sickbeard.USE_NZBS and $sickbeard.USE_TORRENTS and $GenericProvider.NZB == $cur_provider.providerType
#set $bad_url = not $cur_url and cur_provider.is_enabled() #set $bad_url = not $cur_url and cur_provider.is_enabled()
#set $tip = ($cur_provider.name + ('', ' (enable for link)')[not $cur_url and not cur_provider.is_enabled()], #set $tip = ($cur_provider.name + ('', ' (enable for link)')[not $cur_url and not cur_provider.is_enabled()],
'Site Down')[$bad_url] 'Site Down')[$bad_url]
#set $state = ('', ' <span class="red-text">(Site Down?)</span>')[$bad_url] #set $state = ('', ' <span class="red-text">(Site Down?)</span>')[$bad_url]
<li class="ui-state-default" id="$cur_name"> <li class="ui-state-default row-#echo ('odd', 'even')[$show_type or not $sickbeard.USE_TORRENTS]#" id="$cur_name">
<input type="checkbox" id="enable_$cur_name" class="provider_enabler" <%= html_checked if cur_provider.is_enabled() else '' %>/> <input type="checkbox" id="enable_$cur_name" class="provider_enabler" <%= html_checked if cur_provider.is_enabled() else '' %>/>
<a class="imgLink" #if $cur_url#href="<%= anon_url(cur_url) %>" onclick="window.open(this.href,'_blank');return false;"#else#name=""#end if# rel="noreferrer"><img src="$sbRoot/images/providers/$cur_provider.image_name()" alt="$tip" title="$tip" width="16" height="16" style="vertical-align:middle" /></a> <a class="imgLink" #if $cur_url#href="<%= anon_url(cur_url) %>" onclick="window.open(this.href,'_blank');return false;"#else#name=""#end if# rel="noreferrer"><img src="$sbRoot/images/providers/$cur_provider.image_name()" alt="$tip" title="$tip" width="16" height="16" style="vertical-align:middle" /></a>
<span style="vertical-align:middle">$cur_provider.name$state</span> <span style="vertical-align:middle">$cur_provider.name$state</span>
#if $cur_provider.is_public_access() and type($cur_provider).__name__ not in ['TorrentRssProvider'] #if $cur_provider.is_public_access() and type($cur_provider).__name__ not in ['TorrentRssProvider']
<span style="font-size:10px;vertical-align:top;font-weight:normal">(PA)</span> <span style="font-size:10px;vertical-align:top;font-weight:normal">(PA)</span>
#end if# #end if#
#if $show_type
<span style="font-size:10px;vertical-align:top;font-weight:normal">($cur_provider.providerType)</span>
#end if#
#if not $cur_provider.supports_backlog#*#end if# #if not $cur_provider.supports_backlog#*#end if#
<span class="ui-icon ui-icon-arrowthick-2-n-s pull-right" style="margin-top:3px"></span> <span class="ui-icon ui-icon-arrowthick-2-n-s pull-right" style="margin-top:3px"></span>
</li> </li>

View file

@ -1,75 +1,73 @@
#import sickbeard #import sickbeard
#import datetime #from sickbeard import indexerApi, indexermapper, network_timezones
#import re #from sickbeard.common import Overview, qualityPresets, qualityPresetStrings, \
#from sickbeard import subtitles, sbdatetime, network_timezones Quality, statusStrings, WANTED, SKIPPED, ARCHIVED, IGNORED, FAILED, DOWNLOADED
#import sickbeard.helpers #from sickbeard.helpers import anon_url, get_size, human, maybe_plural
#from sickbeard.common import *
#from sickbeard.helpers import anon_url
#from lib import subliminal
#from sickbeard.indexers.indexer_config import INDEXER_TVDB, INDEXER_IMDB #from sickbeard.indexers.indexer_config import INDEXER_TVDB, INDEXER_IMDB
<% def sg_var(varname, default=False): return getattr(sickbeard, varname, default) %>#slurp#
<% def sg_str(varname, default=''): return getattr(sickbeard, varname, default) %>#slurp#
## ##
#set global $title = $show.name #set global $title = $show.name
#set global $topmenu = 'home' #set global $topmenu = 'home'
#set $exceptions_string = ', '.join($show.exceptions) #set $exceptions_string = ', '.join($show.exceptions)
#set global $page_body_attr = 'display-show' #set $css = $getVar('css', 'reg')
#set $has_art = $getVar('has_art', None)
#set $restart = 'Restart SickGear for new features on this page'
#set $show_message = ($show_message, $restart)[None is $has_art]
#set global $page_body_attr = 'display-show" class="' + $css
#set theme_suffix = ('', '-dark')['dark' == $sg_str('THEME_NAME', 'dark')]
## ##
#import os.path, os #import os.path, os
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_top.tmpl') #include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_top.tmpl')
<script type="text/javascript" src="$sbRoot/js/lib/jquery.bookmarkscroll.js?v=$sbPID"></script>
<input type="hidden" id="sbRoot" value="$sbRoot"> <input type="hidden" id="sbRoot" value="$sbRoot">
<script>
<!--
var config = {
hasArt: #echo ('!0', '!1')[not $has_art]#,
TVShowList: [${tvshow_id_csv}],
useIMDbInfo: #echo ('!1', '!0')[$sg_var('USE_IMDB_INFO')]
}
\$.SickGear.config = {
useFuzzy: #echo ('!1', '!0')[$sg_var('FUZZY_DATING')]#,
#if $sg_var('FUZZY_DATING')##slurp#
dateFormat: '$sg_str('DATE_PRESET', '%x')',
timeFormat: '$sg_str('TIME_PRESET', '%I:%M %p')',
fuzzyTrimZero: #echo ('!1', '!0')[$sg_var('TRIM_ZERO')]#
#end if##slurp#
}
//-->
</script>
<script type="text/javascript" src="$sbRoot/js/displayShow.js?v=$sbPID"></script> <script type="text/javascript" src="$sbRoot/js/displayShow.js?v=$sbPID"></script>
<script type="text/javascript" src="$sbRoot/js/plotTooltip.js?v=$sbPID"></script> <script type="text/javascript" src="$sbRoot/js/plotTooltip.js?v=$sbPID"></script>
<script type="text/javascript" src="$sbRoot/js/sceneExceptionsTooltip.js?v=$sbPID"></script> <script type="text/javascript" src="$sbRoot/js/sceneExceptionsTooltip.js?v=$sbPID"></script>
#if $sickbeard.USE_IMDB_INFO #if $sg_var('USE_IMDB_INFO')
<script type="text/javascript" src="$sbRoot/js/ratingTooltip.js?v=$sbPID"></script> <script type="text/javascript" src="$sbRoot/js/ratingTooltip.js?v=$sbPID"></script>
#end if #end if
<script type="text/javascript" src="$sbRoot/js/ajaxEpSearch.js?v=$sbPID"></script> <script type="text/javascript" src="$sbRoot/js/ajaxEpSearch.js?v=$sbPID"></script>
<script type="text/javascript" src="$sbRoot/js/ajaxEpSubtitles.js?v=$sbPID"></script> <script type="text/javascript" src="$sbRoot/js/ajaxEpSubtitles.js?v=$sbPID"></script>
<script type="text/javascript" src="$sbRoot/js/lib/jquery.bookmarkscroll.js?v=$sbPID"></script>
<script type="text/javascript" src="$sbRoot/js/lib/jquery.collapser.min.js?v=$sbPID"></script> <script type="text/javascript" src="$sbRoot/js/lib/jquery.collapser.min.js?v=$sbPID"></script>
<script type="text/javascript" charset="utf-8">
<!-- <style>
\$(document).ready(function(){ .bfr{position:absolute;left:-999px;top:-999px}.bfr img{width:16px;height:16px}.spinner{display:inline-block;width:16px;height:16px;background:url(${sbRoot}/images/loading16${theme_suffix}.gif) no-repeat 0 0}
#set $fuzzydate = 'airdate' .images i{margin-right:6px;margin-top:5px}.hide{display:none}
#if $sickbeard.FUZZY_DATING .tvshowImg {border:1px solid transparent;min-width:226px;min-hieght:332px}
fuzzyMoment({ </style>
containerClass: '.${fuzzydate}', <div class="bfr"><img src="$sbRoot/images/loading16${theme_suffix}.gif" /></div>
dateHasTime: !1,
dateFormat: '${sickbeard.DATE_PRESET}', <div id="background-container">
timeFormat: '${sickbeard.TIME_PRESET}', #if $has_art
trimZero: #echo ('!1', '!0')[$sickbeard.TRIM_ZERO]# <ul>
}); #for $k, ($image, $rating) in enumerate($fanart)
<li class="#echo ' '.join((x for x in ({10:'group', 20:'fave', 30:'avoid'}.get($rating, ''), ('', 'background first-load')[$start_image == $k]) if x)) #" style="background-image:url($sbRoot/showPoster/?show=$show.indexerid&which=fanart_$image)"></li>
#end for
</ul>
#end if #end if
#raw </div>
$('.addQTip').each(function () {
$(this).css({'cursor':'help', 'text-shadow':'0px 0px 0.5px #666'});
$(this).qtip({
show: {solo:!0},
position: {viewport:$(window), my:'left center', adjust:{ y: -10, x: 2 }},
style: {classes:'qtip-rounded qtip-shadow qtip-maxwidth'}
});
});
#end raw
#if $sickbeard.USE_IMDB_INFO
\$.fn.generateStars = function() {
return this.each(function(i,e){\$(e).html(\$('<span/>').width(\$(e).text()*12));});
};
\$('.imdbstars').generateStars();
#end if
TVShowList = [${tvshow_id_csv}]
});
//-->
</script>
<div class="displayshow-wrapper reg all"> <div class="displayshow-wrapper">
<div id="change-show" class="pull-left form-inline">
<div class="background-container">
<div style="" class="background"></div>
</div>
<div class="pull-left form-inline">
Change show: Change show:
#set $displayshowlist = [] #set $displayshowlist = []
#set $cur_sel = 0 #set $cur_sel = 0
@ -80,18 +78,19 @@
#set void = $displayshowlist.append('\t\t\t<optgroup label="%s">' % $curShowType) #set void = $displayshowlist.append('\t\t\t<optgroup label="%s">' % $curShowType)
#end if #end if
#for $curShow in $curShowList #for $curShow in $curShowList
#set void = $displayshowlist.append('\t\t\t<option value="%s"%s>%s</option>' % ($curShow.indexerid, ('', ' selected="selected"')[$curShow == $show], $curShow.name)) #set $show_ended = '' != $curShow.status and $curShow.status in ['ended', 'Ended', 'Canceled']
#set void = $displayshowlist.append('\t\t\t<option %svalue="%s"%s>%s</option>' % (('', 'class="ended" ')[$show_ended], $curShow.indexerid, ('', ' selected="selected"')[$curShow == $show], $curShow.name))
#end for #end for
#if 1 < len($sortedShowLists) #if 1 < len($sortedShowLists)
#set void = $displayshowlist.append('\t\t\t</optgroup>') #set void = $displayshowlist.append('\t\t\t</optgroup>')
#end if #end if
#end for #end for
## ##
<div class="navShow"><img id="prevShow" src="$sbRoot/images/prev.png" alt="&lt;&lt;" title="$prev_title" class="addQTip" /></div> <div id="prevShow" class="navShow addQTip" title="$prev_title">&nbsp;</div>
<select id="pickShow" class="form-control form-control-inline input-sm"> <select id="pickShow" class="form-control form-control-inline input-sm">
#echo '\n'.join($displayshowlist)# #echo '\n'.join($displayshowlist)#
</select> </select>
<div class="navShow"><img id="nextShow" src="$sbRoot/images/next.png" alt="&gt;&gt;" title="$next_title" class="addQTip" /></div> <div id="nextShow" class="navShow addQTip" title="$next_title">&nbsp;</div>
</div> </div>
<div class="clearfix" style="margin-bottom:15px"></div> <div class="clearfix" style="margin-bottom:15px"></div>
@ -104,52 +103,46 @@
#end if #end if
<div class="display-show-container"> <div class="display-show-container">
<div id="posterCol" class="hidden-xs"> <div id="posterCol" class="hidden-xs">
<a href="$sbRoot/showPoster/?show=$show.indexerid&amp;which=poster" rel="dialog" title="View poster for $show.name"> <a href="$sbRoot/showPoster/?show=$show.indexerid&amp;which=poster" rel="dialog">
<img src="$sbRoot/showPoster/?show=$show.indexerid&amp;which=poster_thumb" class="tvshowImg" alt="" /> <img src="$sbRoot/showPoster/?show=$show.indexerid&amp;which=poster_thumb" title="View poster for $show.name" class="tvshowImg addQTip" alt="">
</a> </a>
</div> </div>
<div id="showCol" class="display-details"> <div id="showCol">
#if int($show.paused) #if int($show.paused)
<div class="paused paused-highlight"> <div class="paused paused-highlight">
<i class="sgicon-pause paused-outline"></i> <i class="sgicon-pause paused-outline"></i>
</div> </div>
#end if #end if
<div id="details-wrapper"> <div class="details-wrapper">
<div id="details-right"> <div class="details-right top">
#if 0 < len($seasonResults) #if 0 < len($seasons)
##There is a special/season_0?## #set $show_ended = '' != $show.status and $show.status in ['ended', 'Ended', 'Canceled']
#set $season_special = (0, 1)[0 == int($seasonResults[-1]['season'])]
##
#if not $sickbeard.DISPLAY_SHOW_SPECIALS and $season_special
$seasonResults.pop(-1)
#end if
<div> <div>
#if $season_special #if $getVar('has_special', 0 == $seasons[-1][0])
<span class="details-title">Specials</span> <span class="details-title">Specials</span>
<span class="details-info">#if sickbeard.DISPLAY_SHOW_SPECIALS#<a href="#season-0">View</a><span style="margin:0 10px">-</span>#end if#<a class="inner" href="$sbRoot/toggleDisplayShowSpecials/?show=$show.indexerid">#echo ('Show', 'Hide')[sickbeard.DISPLAY_SHOW_SPECIALS]#</a></span> <span class="details-info">#if $sg_var('DISPLAY_SHOW_SPECIALS')#<a href="#season-0">View</a><span style="margin:0 7px">-</span>#end if#<a class="inner" href="$sbRoot/toggleDisplayShowSpecials/?show=$show.indexerid">#echo ('Show', 'Hide')[$sg_var('DISPLAY_SHOW_SPECIALS')]#</a></span>
#end if #end if
</div> </div>
#set $many_seasons = 12 < len($seasonResults) #set $many_seasons = 12 < len($seasons)
<div class="details-seasons"> <div class="details-seasons">
<span class="details-title#echo ('', ' combo-seasons')[$many_seasons]#">Season</span> <span class="details-title#echo ('', ' combo-seasons')[$many_seasons]#">Season</span>
<span class="details-info"> <span class="details-info">
#set $season_list = [s[0] for s in $seasons]
#if $many_seasons #if $many_seasons
<select id="seasonJump" class="form-control form-control-inline input-sm"> <select id="seasonJump" class="form-control form-control-inline input-sm">
<option value="jump">Jump to season</option> <option value="jump">Jump to season</option>
#for $seasonNum in $seasonResults #for $number in $season_list
#if 0 == int($seasonNum['season']) #if 0 != $number
#continue <option value="#season-$number">Season $number</option>
#end if #end if
<option value="#season-$seasonNum['season']">Season $seasonNum['season']</option>
#end for #end for
</select> </select>
#else: #else
#for $seasonNum in $seasonResults #for $number in $season_list
#if 0 == int($seasonNum['season']) #if 0 != $number
#continue <a href="#season-$number">$number</a>
#end if #end if
<a href="#season-$seasonNum['season']">$seasonNum['season']</a>
#end for #end for
#end if #end if
</span> </span>
@ -159,12 +152,12 @@
<div id="details-top"> <div id="details-top">
<div id="showtitle" data-showname="$show.name"> <div id="showtitle" data-showname="$show.name">
<h2 class="title" id="scene_exception_$show.indexerid"><span>$show.name</span></h2> <h2 class="title" id="scene_exception_$show.indexerid"><span>$show.name</span>#echo ('', '<em id="title-status"> (ended)</em>')[$show_ended]#</h2>
#set $genres_done = False #set $genres_done = False
#if $sickbeard.USE_IMDB_INFO and 'genres' in $show.imdb_info and '' != $show.imdb_info['genres'] #if $sg_var('USE_IMDB_INFO') and 'genres' in $show.imdb_info and '' != $show.imdb_info['genres']
#for $imdbgenre in $show.imdb_info['genres'].split('|') #for $imdbgenre in $show.imdb_info['genres'].split('|')
#set $genres_done = True #set $genres_done = True
<span class="label"><a href="<%= anon_url('http://www.imdb.com/search/title?at=0&genres=', imdbgenre.lower().replace('-','_'),'&amp;sort=moviemeter,asc&amp;title_type=tv_series') %>" target="_blank" title="View other popular $imdbgenre shows on imdb.com">$imdbgenre.replace('Sci-Fi','Science-Fiction')</a></span> <span class="label"><a href="<%= anon_url('http://www.imdb.com/search/title?at=0&genres=', imdbgenre.lower().replace('-','_'),'&amp;sort=moviemeter,asc&amp;title_type=tv_series') %>" target="_blank" title="View other popular $imdbgenre shows on imdb.com" class="addQTip">$imdbgenre.replace('Sci-Fi','Science-Fiction')</a></span>
#end for #end for
#end if #end if
#if not $genres_done and $show.genre #if not $genres_done and $show.genre
@ -180,45 +173,47 @@
</div> </div>
</div> </div>
<div id="details-wrapper"> <div class="details-wrapper">
<div id="details-right"> <div class="details-right">
<div> <div>
<span class="details-title">Links</span> <span class="details-title">Links</span>
<span class="details-info"> <span class="details-info">
#set $tvdb_id = None #set $tvdb_id = None
#for $src_id, $src_name in $sickbeard.indexerApi().all_indexers.iteritems() #for $src_id, $src_name in $indexerApi().all_indexers.iteritems()
#if sickbeard.indexerApi($src_id).config.get('defunct') and $src_id != $show.indexer #if $indexerApi($src_id).config.get('defunct') and $src_id != $show.indexer
#continue #continue
#end if #end if
#if $src_id in $show.ids and $show.ids[$src_id].get('id', 0) > 0 and $sickbeard.indexermapper.MapStatus.NOT_FOUND != $show.ids[$src_id]['status'] #if $src_id in $show.ids and $show.ids[$src_id].get('id', 0) > 0 and $indexermapper.MapStatus.NOT_FOUND != $show.ids[$src_id]['status']
#if $INDEXER_TVDB == $src_id #if $INDEXER_TVDB == $src_id
#set $tvdb_id = $show.ids[$src_id]['id'] #set $tvdb_id = $show.ids[$src_id]['id']
#end if #end if
#if $INDEXER_IMDB == $src_id and not $sickbeard.USE_IMDB_INFO #if $INDEXER_IMDB == $src_id and not $sg_var('USE_IMDB_INFO')
#continue #continue
#end if #end if
#if not sickbeard.indexerApi($src_id).config.get('defunct') #if not $indexerApi($src_id).config.get('defunct')
<a class="service" href="$anon_url(sickbeard.indexerApi($src_id).config['show_url'], $show.ids[$src_id]['id'])" onclick="window.open(this.href, '_blank'); return !1;" title="View $src_name info in new tab"> <a class="service addQTip" href="$anon_url($indexerApi($src_id).config['show_url'], $show.ids[$src_id]['id'])" rel="noreferrer" onclick="window.open(this.href, '_blank'); return !1;" title="View $src_name info in new tab">
#else# #else#
<a class="service" href="$sbRoot/home/editShow?show=$show.indexerid#core-component-group3" title="Edit related show IDs"> <a class="service addQTip" href="$sbRoot/home/editShow?show=$show.indexerid#core-component-group3" title="Edit related show IDs">
#end if# #end if#
<img alt="$src_name" height="16" width="16" src="$sbRoot/images/$sickbeard.indexerApi($src_id).config['icon']" /> <img alt="$src_name" height="16" width="16" src="$sbRoot/images/$indexerApi($src_id).config['icon']" />
</a> </a>
#end if #end if
#end for #end for
##if $tvdb_id #if $has_art and $tvdb_id
## <a class="service" href="$anon_url('https://fanart.tv/series/', $tvdb_id)" onclick="window.open(this.href, '_blank'); return !1;" title="View Fanart.tv info in new tab"><img alt="Fanart.tv" height="16" width="16" src="$sbRoot/images/fanart.png" /></a> <a class="service addQTip" href="$anon_url('https://fanart.tv/series/', $tvdb_id)" rel="noreferrer" onclick="window.open(this.href, '_blank'); return !1;" title="View Fanart.tv info in new tab">
##end if <img alt="Fanart.tv" height="16" width="16" src="$sbRoot/images/fanart.png" />
</a>
#end if
#if $xem_numbering or $xem_absolute_numbering #if $xem_numbering or $xem_absolute_numbering
<a class="service" href="$anon_url('http://thexem.de/search?q=', $show.name)" rel="noreferrer" onclick="window.open(this.href, '_blank'); return !1;" title="View XEM info in new tab"><img alt="[xem]" height="16" width="16" src="$sbRoot/images/xem.png" /></a> <a class="service addQTip" href="$anon_url('http://thexem.de/search?q=', $show.name)" rel="noreferrer" onclick="window.open(this.href, '_blank'); return !1;" title="View XEM info in new tab"><img alt="[xem]" height="16" width="16" src="$sbRoot/images/xem.png" /></a>
#end if #end if
</span> </span>
</div> </div>
#set $startyear, $flags, $runtime = (None, False, None) #set $startyear, $flags, $runtime = (None, False, None)
#if $sickbeard.USE_IMDB_INFO and $show.imdbid #if $sg_var('USE_IMDB_INFO') and $show.imdbid
#if 'year' in $show.imdb_info #if 'year' in $show.imdb_info
#set $startyear = $show.imdb_info['year'] #set $startyear = $show.imdb_info['year'] or None
#end if #end if
#set $flags = 'country_codes' in $show.imdb_info and '' != $show.imdb_info['country_codes'] #set $flags = 'country_codes' in $show.imdb_info and '' != $show.imdb_info['country_codes']
#if 'runtimes' in $show.imdb_info #if 'runtimes' in $show.imdb_info
@ -231,7 +226,7 @@
#if None is $runtime and $show.runtime #if None is $runtime and $show.runtime
#set $runtime = $show.runtime #set $runtime = $show.runtime
#end if #end if
#if None is not $startyear or $flags #if $startyear or $flags
<div> <div>
<span class="details-title">Premiered</span> <span class="details-title">Premiered</span>
<span class="details-info"> <span class="details-info">
@ -249,7 +244,7 @@
#set $showairs = '%s%s' % ($show.airs.replace('y', 'y,'), #set $showairs = '%s%s' % ($show.airs.replace('y', 'y,'),
('', ' <span class="red-text" style="font-weight:bold">(invalid timeformat)</span>')[not $network_timezones.test_timeformat($show.airs)]) ('', ' <span class="red-text" style="font-weight:bold">(invalid timeformat)</span>')[not $network_timezones.test_timeformat($show.airs)])
<div> <div>
<span class="details-title">Airs</span> <span class="details-title">Air#echo ('s', 'ed')[$show_ended]#</span>
<span class="details-info">$showairs</span> <span class="details-info">$showairs</span>
</div> </div>
#end if #end if
@ -266,18 +261,18 @@
<span class="details-info">$runtime minutes</span> <span class="details-info">$runtime minutes</span>
</div> </div>
#end if #end if
#if '' != $show.status #if $show.status
<div> <div>
<span class="details-title">Status</span> <span class="details-title">Status</span>
<span class="details-info">$show.status</span> <span class="details-info">$show.status</span>
</div> </div>
#end if #end if
#if $sickbeard.USE_IMDB_INFO and 'rating' in $show.imdb_info #if $sg_var('USE_IMDB_INFO') and 'rating' in $show.imdb_info
<div> <div>
<span class="details-title">IMDb rating</span> <span class="details-title">IMDb rating</span>
<span class="details-info"> <span class="details-info">
#if '' != $show.imdb_info['votes'] #if $show.imdb_info['votes']
#set $rating_tip = '%s of 10 stars<br />%s votes' % (str($show.imdb_info['rating']), str($show.imdb_info['votes'])) #set $rating_tip = '%s of 10 stars<br />%s votes' % (str($show.imdb_info['rating']), str($show.imdb_info['votes']))
<span class="imdbstars" qtip-content="$rating_tip">$show.imdb_info['rating']</span> <span class="imdbstars" qtip-content="$rating_tip">$show.imdb_info['rating']</span>
#else #else
@ -295,7 +290,7 @@
<span class="quality $qualityPresetStrings[$show.quality]">$qualityPresetStrings[$show.quality]</span> <span class="quality $qualityPresetStrings[$show.quality]">$qualityPresetStrings[$show.quality]</span>
</span> </span>
</div> </div>
#else: #else
#if $anyQualities #if $anyQualities
<div> <div>
<span class="details-title">Initial</span> <span class="details-title">Initial</span>
@ -316,21 +311,37 @@
</div> </div>
<div id="details-left"> <div id="details-left">
<div class="details-plot#echo ('', ' no-plot')['' == $show.overview]#"> #set $has_overview = '' != $show.overview
#echo ('No plot overview available', $show.overview)['' != $show.overview]# #set $ep_tally = ('', '(<span class="hint">%s episodes</span>)' % $ep_counts['eps_all'])[0 < $ep_counts['eps_all']]
<div class="#echo ('no', 'details')[$has_overview]#-plot">
$ep_tally
#if $has_overview
$show.overview
#else
#echo ('', '<br /><br />')[any($ep_tally)]
#if $show_ended
#if $varExists('force_update')
A <a href="/$force_update" title="Trigger force full update">force full update</a> may return a plot overview for this ended show
#else
Restart SickGear to get a new link here for this ended show
#end if
#else
No plot overview available
#end if
#end if
</div> </div>
<div id="details-bottom"> <div id="details-bottom">
<span class="label addQTip" title="Info language, $show.lang"><img src="$sbRoot/images/flags/${show.lang}.png" width="16" height="11" alt="" style="margin-top:-1px" /></span> <span class="label addQTip" title="Info language, $show.lang"><img src="$sbRoot/images/flags/${show.lang}.png" width="16" height="11" alt="" style="margin-top:-1px" /></span>
<span class="label addQTip" title="Location#echo (' no longer exists" style="background-color:#8f1515"', '"')[$showLoc[1]]#>$showLoc[0]</span> <span class="label addQTip" title="Location#echo (' no longer exists" style="background-color:#8f1515"', '"')[$showLoc[1]]#>$showLoc[0]</span>
<span class="label addQTip" title="Size">$sickbeard.helpers.human(sickbeard.helpers.get_size($showLoc[0]))</span> <span class="label addQTip" title="Size">$human($get_size($showLoc[0]))</span>
#set $filecount = sum([$c for $k, $c in $epCounts['videos'].items()]) #set $filecount = sum([$c for $k, $c in $ep_counts['videos'].items()])
<span class="label addQTip" title="Videos">$filecount file$sickbeard.helpers.maybe_plural($filecount)</span> <span class="label addQTip" title="Videos">#echo ('No', $filecount)[0 < $filecount]# file$maybe_plural($filecount)</span>
#if $show.paused #if $show.paused
<span class="label label-paused">Paused</span> <span class="label label-paused">Paused</span>
#end if #end if
#if ($anyQualities + $bestQualities) and int($show.archive_firstmatch) #if ($anyQualities + $bestQualities) and int($show.archive_firstmatch)
<span class="label">End upgrade on first match</span> <span class="label">Upgrade once</span>
#end if #end if
#if $show.exceptions #if $show.exceptions
<span class="label addQTip" title="$exceptions_string.replace(', ', '<br />')">Scene names</span> <span class="label addQTip" title="$exceptions_string.replace(', ', '<br />')">Scene names</span>
@ -341,7 +352,7 @@
#if $show.rls_require_words #if $show.rls_require_words
<span class="label addQTip" title="#echo $show.rls_require_words.replace(',', '<br />')#">Required words</span> <span class="label addQTip" title="#echo $show.rls_require_words.replace(',', '<br />')#">Required words</span>
#end if #end if
#if $show.flatten_folders or $sickbeard.NAMING_FORCE_FOLDERS #if $show.flatten_folders or $sg_var('NAMING_FORCE_FOLDERS')
<span class="label">Flat folders</span> <span class="label">Flat folders</span>
#end if #end if
#if int($show.air_by_date) #if int($show.air_by_date)
@ -353,7 +364,7 @@
#if int($show.scene) #if int($show.scene)
<span class="label">Scene numbering</span> <span class="label">Scene numbering</span>
#end if #end if
#if $sickbeard.USE_SUBTITLES and int($show.subtitles) #if $sg_var('USE_SUBTITLES') and int($show.subtitles)
<span class="label">Subtitles</span> <span class="label">Subtitles</span>
#end if #end if
#if int($show.is_sports) #if int($show.is_sports)
@ -363,10 +374,10 @@
<span class="label">Anime</span> <span class="label">Anime</span>
#end if #end if
#if $bwl and $bwl.whitelist #if $bwl and $bwl.whitelist
<span class="label addQTip" title="#echo ', '.join($bwl.whitelist).replace(',', '<br />')#">Wanted group$sickbeard.helpers.maybe_plural(len($bwl.whitelist))</span> <span class="label addQTip" title="#echo ', '.join($bwl.whitelist).replace(',', '<br />')#">Wanted group$maybe_plural(len($bwl.whitelist))</span>
#end if #end if
#if $bwl and $bwl.blacklist #if $bwl and $bwl.blacklist
<span class="label addQTip" title="#echo ', '.join($bwl.blacklist).replace(',', '<br />')#">Unwanted group$sickbeard.helpers.maybe_plural(len($bwl.blacklist))</span> <span class="label addQTip" title="#echo ', '.join($bwl.blacklist).replace(',', '<br />')#">Unwanted group$maybe_plural(len($bwl.blacklist))</span>
#end if #end if
</div> </div>
</div> </div>
@ -376,7 +387,7 @@
<div class="clearfix"></div> <div class="clearfix"></div>
<div class="pull-left"> <div id="change-status" class="pull-left">
<p style="margin-bottom:5px">Change selected episodes to</p> <p style="margin-bottom:5px">Change selected episodes to</p>
<select id="statusSelect" class="form-control form-control-inline input-sm"> <select id="statusSelect" class="form-control form-control-inline input-sm">
#for $curStatus in [$WANTED, $SKIPPED, $ARCHIVED, $IGNORED, $FAILED] + sorted($Quality.DOWNLOADED) #for $curStatus in [$WANTED, $SKIPPED, $ARCHIVED, $IGNORED, $FAILED] + sorted($Quality.DOWNLOADED)
@ -392,12 +403,12 @@
</div> </div>
<div class="pull-right clearfix" id="checkboxControls"> <div class="pull-right clearfix" id="checkboxControls">
<div style="padding-bottom:5px"> <div style="padding-bottom:5px" class="addQTip" title="Filter Episodes">
<label for="wanted"><span class="wanted"><input type="checkbox" id="wanted" checked="checked"> Wanted: <b>$epCounts[$Overview.WANTED]</b></span></label> <label for="good"><span class="good"><input type="checkbox" id="good" checked="checked"> Downloaded: <b>$ep_counts[$Overview.GOOD]</b></span></label>
<label for="qual"><span class="qual"><input type="checkbox" id="qual" checked="checked"> Low quality: <b>$epCounts[$Overview.QUAL]</b></span></label> <label for="snatched"><span class="snatched"><input type="checkbox" id="snatched" checked="checked"> Snatched: <b>$ep_counts[$Overview.SNATCHED]</b></span></label>
<label for="good"><span class="good"><input type="checkbox" id="good" checked="checked"> Downloaded: <b>$epCounts[$Overview.GOOD]</b></span></label> <label for="wanted"><span class="wanted"><input type="checkbox" id="wanted" checked="checked"> Wanted: <b>$ep_counts[$Overview.WANTED]</b></span></label>
<label for="skipped"><span class="skipped"><input type="checkbox" id="skipped" checked="checked"> Skipped: <b>$epCounts[$Overview.SKIPPED]</b></span></label> <label for="qual"><span class="qual"><input type="checkbox" id="qual" checked="checked"> Low Quality: <b>$ep_counts[$Overview.QUAL]</b></span></label>
<label for="snatched"><span class="snatched"><input type="checkbox" id="snatched" checked="checked"> Snatched: <b>$epCounts[$Overview.SNATCHED]</b></span></label> <label for="skipped"><span class="skipped"><input type="checkbox" id="skipped" checked="checked"> Skipped: <b>$ep_counts[$Overview.SKIPPED]</b></span></label>
</div> </div>
<div class="pull-right" > <div class="pull-right" >
@ -407,207 +418,94 @@
</div> </div>
<div class="clearfix"></div> <div class="clearfix"></div>
#set $curSeason = -1 #if not len($seasons)
#set $odd = 0 <div id="no-episode-data">
#set $scene, $scene_anime = (False, False) <h3>No episode details at TV info source
#if not $show.air_by_date and not $show.is_sports and not $show.is_anime and $show.is_scene <a class="service" href="$anon_url($indexerApi($show.indexer).config['show_url'], $show.indexerid)" onclick="window.open(this.href, '_blank'); return !1;" title="View $indexerApi($show.indexer).name info in new tab">$indexerApi($show.indexer).name</a>
#set $scene = True
#elif not $show.air_by_date and not $show.is_sports and $show.is_anime and $show.is_scene
#set $scene_anime = True
#end if
##
#if 0 == len($sqlResults)
<div style="margin-top:50px">
<h3>Episodes do not exist for this show at the associated indexer
<a class="service" href="$anon_url(sickbeard.indexerApi($show.indexer).config['show_url'], $show.indexerid)" onclick="window.open(this.href, '_blank'); return !1;" title="View $sickbeard.indexerApi($show.indexer).name info in new tab">$sickbeard.indexerApi($show.indexer).name</a>
</h3> </h3>
</div> </div>
#else: #else
#set $network_timezone = $network_timezones.get_network_timezone($show.network) #set $working_season = -1
#set $network_time = $network_timezones.parse_time($show.airs) #set $odd = 0
#for $epResult in $sqlResults #set $scene, $scene_anime = (False, False)
#set $epStr = '%sx%s' % ($epResult['season'], $epResult['episode']) #if not $show.air_by_date and not $show.is_sports and not $show.is_anime and $show.is_scene
#if not $epStr in $epCats or (0 == int($epResult['season']) and not $sickbeard.DISPLAY_SHOW_SPECIALS) #set $scene = True
#elif not $show.air_by_date and not $show.is_sports and $show.is_anime and $show.is_scene
#set $scene_anime = True
#end if
#for $season, $episodes in $seasons
#for $ep in $episodes
#if None is not $ep
#set $ep_str = '%sx%s' % ($season, $ep['episode'])
#if $ep_str not in $ep_cats or (0 == $season and not $sg_var('DISPLAY_SHOW_SPECIALS'))
#continue #continue
#end if #end if
## #end if
#if $curSeason != int($epResult['season'])
#if 0 <= $curSeason #if $working_season != $season
#if 0 <= $working_season
</tbody> </tbody>
</table> </table>
#end if #end if
#set $working_season = $season
<table class="sickbeardTable" cellspacing="0" border="0" cellpadding="0"> #set $human_season = ('Season %s' % $season, 'Specials')[0 == $season]
<tr id="season-$epResult['season']"> ## one off variable migration, on next version apply... (s/$getVar('display_seasons', [])/[]/),
<table class="sickbeardTable#echo '%s%s%s' % (('', ' season-min')[$season in $getVar('season_min', $getVar('display_seasons', []))], ('', ' latest-season')[$latest_season == $season], ('', ' open')[$season in $getVar('other_seasons', [])])#">
<thead>
<tr>
<th class="row-seasonheader" colspan="13"> <th class="row-seasonheader" colspan="13">
#if None is $has_art#<span class="red-text pull-right">Restart SickGear to reveal new options here</span>
<button id="showseason-$epResult['season']" type="button" class="btn btn-default pull-right#echo '%s%s' % (('', ' display-season')[int($epResult['season']) in $display_seasons], ('', ' latest-season')[$latest_season == int($epResult['season'])])#" data-toggle="collapse" data-target="#collapseSeason-$epResult['season']">Show episodes<span class="sgicon-arrowdown" style="margin-left:4px"></span></button> #elif not (1 == $lowest_season and 1 == $latest_season and $latest_season >= $highest_season)
#set $videos = 'none' if $epResult['season'] not in $epCounts['videos'] else $epCounts['videos'][$epResult['season']] <button id="showseason-$season" type="button" class="btn btn-default pull-right"><span class="onshow">Show $human_season.lower()<i class="sgicon-arrowdown"></i></span><span class="onhide">Hide $human_season.lower()<i class="sgicon-arrowup"></i></span></button>
#set $archived = False if $epResult['season'] not in $epCounts['archived'] else $epCounts['archived'][$epResult['season']] <button type="button" class="btn btn-default pull-right allseasons"><span class="onshow">Show all</span><span class="onhide">Hide most</span><i class="icon-glyph"></i></button>
<h3><a name="season-$epResult['season']"></a>#if 0 == int($epResult['season']) then 'Specials' else 'Season ' + str($epResult['season']) <span class="images pull-right hide"><i class="spinner"></i></span>
<span class="season-status"><b>[</b> <span class="footerhighlight">$videos</span> / <span class="footerhighlight">$epCounts['totals'][$epResult['season']]</span><span class="archived-count">#echo ('', '&nbsp;with <span class="footerhighlight">%s</span> archived' % $archived)[0 < $archived]#</span> <b>]</b></span> #end if
#set $videos = '0' if $season not in $ep_counts['videos'] else $ep_counts['videos'][$season]
#set $season_stats = $ep_counts['status'].get($season, {})
#set $snatched = $season_stats.get($Overview.SNATCHED, None)
#set $wanted = $season_stats.get($Overview.WANTED, None)
#set $qual = $season_stats.get($Overview.QUAL, None)
#set $archived = False if $season not in $ep_counts['archived'] else $ep_counts['archived'][$season]
<h3>$human_season<a id="season-$season" name="season-$season"></a>
#if None is not $has_art
<span class="season-status"><span class="good status-badge">&nbsp;D: <strong>$videos</strong>&nbsp;</span>#if snatched#<span class="snatched status-badge">&nbsp;S: <strong>$snatched</strong>&nbsp;</span>#end if##if $wanted#<span class="wanted status-badge">&nbsp;W: <strong>$wanted</strong>&nbsp;</span>#end if##if $qual#<span class="qual status-badge">&nbsp;LQ: <strong>$qual</strong>&nbsp;</span>#end if#&nbsp;of&nbsp;<span class="footerhighlight">$ep_counts['totals'][$season]</span><span class="archived-count">#echo ('', '&nbsp;with <span class="footerhighlight">%s</span> archived' % $archived)[0 < $archived]#</span></span>
#end if
</h3> </h3>
</th> </th>
</tr> </tr>
#set $attr_title_ep = ('', ' (Anime #)')[$show.is_anime]
<tbody id="collapseSeason-$epResult['season']" class="collapse#echo '%s%s' % (('', ' display-season')[int($epResult['season']) in $display_seasons], ('', ' latest-season')[$latest_season == int($epResult['season'])])#"> <tr id="season-$season-cols" class="seasoncols collapse tablesorter-headerRow">
<td class="col-checkbox tablesorter-no-sort"><input type="checkbox" class="seasonCheck" id="$season"></td>
<tr id="season-$epResult['season']-cols" class="seasoncols"> <th class="col-metadata tablesorter-no-sort">Meta</th>
<th class="col-checkbox"><input type="checkbox" class="seasonCheck" id="$epResult['season']"></th> <th class="col-ep tablesorter-ep-num"><span title="Ep #$attr_title_ep">#</span></th>#if $scene or $scene_anime
<th class="col-metadata">NFO</th> <th class="col-ep tablesorter-ep-scene" style="padding-right:18px">Scene#if $scene_anime# absolute#end if#</th>#end if#
<th class="col-metadata">TBN</th>
<th class="col-ep">Episode</th>
#if $show.is_anime
<th class="col-ep">Absolute</th>
#end if
#if $scene
<th class="col-ep">Scene</th>
#end if
#if $scene_anime
<th class="col-ep">Scene absolute</th>
#end if
<th class="col-name">Name</th> <th class="col-name">Name</th>
<th class="col-airdate">Airdate</th> <th class="col-airdate tablesorter-airdate">Air Date</th>#if $sg_var('USE_SUBTITLES') and $show.subtitles
#if $sickbeard.USE_SUBTITLES and $show.subtitles <th class="col-subtitles tablesorter-no-sort">Subtitles</th>#end if
<th class="col-subtitles">Subtitles</th>
#end if
<th class="col-status">Status</th> <th class="col-status">Status</th>
<th class="col-search">Search</th> <th class="col-search tablesorter-no-sort">Search</th>
</tr> </tr>
#set $curSeason = int($epResult['season']) </thead>
<tbody class="collapse">
#end if
#if None is $ep
</tbody>
#continue
#end if #end if
#set $epLoc = $epResult['location'] #set global $episode = $ep
#set never_aired = 0 < $curSeason and 1 == int($epResult['airdate']) #include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_displayShow.tmpl')
#end for
<tr class="#echo ($Overview.overviewStrings[$epCats[$epStr]], 'airdate-never')[$never_aired]##echo ('', ' archived')[ARCHIVED == int($epResult['status'])]# season-$curSeason seasonstyle">
<td class="col-checkbox">
#if $UNAIRED != int($epResult['status']) and not $never_aired
<input type="checkbox" class="epCheck" id="#echo $epStr#" name="#echo $epStr#">
#end if
</td>
<td align="center"><img src="$sbRoot/images/#if int($epResult['hasnfo']) then 'nfo.gif" alt="Yes" title="Yes' else 'nfo-no.gif" alt="No" title="No'#" width="23" height="11" /></td>
<td align="center"><img src="$sbRoot/images/#if int($epResult['hastbn']) then 'tbn.gif" alt="Yes" title="Yes' else 'tbn-no.gif" alt="No" title="No'#" width="23" height="11" /></td>
<td align="center">
#if $epLoc and $show._location and $epLoc.lower().startswith($show._location.lower())
#set $epLoc = $epLoc[len($show._location)+1:]
#elif $epLoc and (not $epLoc.lower().startswith($show._location.lower()) or not $show._location)
#set $epLoc = $epLoc
#end if
#if '' != $epLoc and None != $epLoc
<span title="$epLoc - <strong>$sickbeard.helpers.human($epResult['file_size'])</strong>" class="addQTip">$epResult["episode"]</span>
#else
$epResult['episode']
#end if
</td>
#if $show.is_anime
<td align="center">$epResult['absolute_number']</td>
#end if
#if $scene
#set $dfltSeas, $dfltEpis = (0, 0) if ($epResult['season'], $epResult['episode']) not in $xem_numbering else $xem_numbering[($epResult['season'], $epResult['episode'])]
<td align="center">
<input type="text" placeholder="#echo '%sx%s' % ($dfltSeas, $dfltEpis)#" size="6" maxlength="8"
class="sceneSeasonXEpisode form-control input-scene" data-for-season="$epResult['season']" data-for-episode="$epResult['episode']"
id="#echo 'sceneSeasonXEpisode_%s_%s_%s' % ($show.indexerid, $epResult['season'], $epResult['episode'])#"
title="Change the value here if scene numbering differs from the indexer episode numbering"
#if ($epResult['season'], $epResult['episode']) in $scene_numbering
#set $scSeas, $scEpis = $scene_numbering[($epResult['season'], $epResult['episode'])]
value="#echo '%sx%s' % ($scSeas, $scEpis)#"
#else
value=""
#end if
style="padding:0; text-align:center; max-width:60px">
</td>
#elif $scene_anime
#set $dfltAbsolute = 0 if $epResult['absolute_number'] not in $xem_absolute_numbering else $xem_absolute_numbering[$epResult['absolute_number']]
<td align="center">
<input type="text" placeholder="$dfltAbsolute" size="6" maxlength="8"
class="sceneAbsolute form-control input-scene" data-for-absolute="$epResult['absolute_number']"
id="#echo 'sceneAbsolute_%s_%s' % ($show.indexerid, $epResult['absolute_number'])#"
title="Change the value here if scene absolute numbering differs from the indexer absolute numbering"
#if $epResult['absolute_number'] in $scene_absolute_numbering
value="$scene_absolute_numbering[$epResult['absolute_number']]"
#else
value=""
#end if
style="padding:0; text-align:center; max-width:60px" />
</td>
#end if
<td class="col-name">
<img src="$sbRoot/images/info32.png" width="16" height="16" alt="" class="plotInfo#echo '%s" />' %\
('None', ('" id="plot_info_%s_%s_%s' % ($show.indexerid, $epResult['season'], $epResult['episode'])))[None is not $epResult['description'] and '' != $epResult['description']]#
<%= '<em class="tba grey-text">TBA</em>' if not epResult['name'] or 'TBA' == epResult['name'] else epResult['name'] %>
</td>
<td class="col-airdate">
<span class="${fuzzydate}"#if $sickbeard.FUZZY_DATING# data-fulldate="$sbdatetime.sbdatetime.sbfdate(dt=$datetime.date.fromordinal($epResult['airdate']), d_preset='%A, %B %d, %Y')"#end if#>#if 1 == int($epResult['airdate']) then 'never' else $sbdatetime.sbdatetime.sbfdate($sbdatetime.sbdatetime.convert_to_setting($network_timezones.parse_date_time($epResult['airdate'], $network_time, $network_timezone)))#</span>
</td>
#if $sickbeard.USE_SUBTITLES and $show.subtitles
<td class="col-subtitles" align="center">
#if $epResult['subtitles']
#for $sub_lang in subliminal.language.language_list($epResult['subtitles'].split(','))
#if '' != sub_lang.alpha2
<img src="$sbRoot/images/flags/${sub_lang.alpha2}.png" width="16" height="11" alt="${sub_lang}" />
#end if
#end for #end for
#end if
</td>
#end if
#set $curStatus, $curQuality = $Quality.splitCompositeStatus(int($epResult['status']))
#if Quality.NONE != $curQuality
<td class="col-status">$statusStrings[$curStatus] <span class="quality $Quality.qualityStrings[$curQuality].replace('720p','HD720p').replace('1080p','HD1080p').replace('RawHD TV', 'RawHD').replace('HD TV', 'HD720p')">$Quality.qualityStrings[$curQuality]</span></td>
#else:
<td class="col-status">$statusStrings[$curStatus]</td>
#end if
<td class="col-search">
#if 0 != int($epResult['season'])
#if (int($epResult['status']) in $Quality.SNATCHED or int($epResult['status']) in $Quality.DOWNLOADED) and $sickbeard.USE_FAILED_DOWNLOADS
<a class="epRetry" id="#echo $epStr#" name="#echo $epStr#" href="$sbRoot/home/retryEpisode?show=$show.indexerid&amp;season=$epResult['season']&amp;episode=$epResult['episode']"><img src="$sbRoot/images/search16.png" height="16" alt="retry" title="Retry download" /></a>
#else:
<a class="epSearch" id="#echo $epStr#" name="#echo $epStr#" href="$sbRoot/home/searchEpisode?show=$show.indexerid&amp;season=$epResult['season']&amp;episode=$epResult['episode']"><img src="$sbRoot/images/search16.png" width="16" height="16" alt="search" title="Manual search" /></a>
#end if
#end if
#if $sickbeard.USE_SUBTITLES and $show.subtitles and len(set(str($epResult['subtitles']).split(',')).intersection(set($subtitles.wantedLanguages()))) < len($subtitles.wantedLanguages()) and $epResult['location']
<a class="epSubtitlesSearch" href="$sbRoot/home/searchEpisodeSubtitles?show=$show.indexerid&amp;season=$epResult['season']&amp;episode=$epResult['episode']"><img src="$sbRoot/images/closed_captioning.png" height="16" alt="search subtitles" title="Search subtitles" /></a>
#end if
</td>
</tr>
#end for
</tbody> </tbody>
</table> </table>
#end if #end if
<script type="text/javascript" charset="utf-8">
#raw
$(document).ready(function(){
$('.details-plot').collapser({
mode: 'lines',
truncate: 10,
showText: '<span class="pull-right moreless"><i class="sgicon-arrowdown" style="margin-right:2px"></i>more</span>',
hideText: '<span class="pull-right moreless"><i class="sgicon-arrowup" style="margin-right:2px"></i>less</span>',
showClass: 'show-class'
});
$('button[data-target*="collapseSeason-"]').each(function(k,v){
var tbl = $($(this).attr('data-target')),
btn = $('#' + $(this).attr('id'));
tbl.on('hide.bs.collapse', function () { btn.html('Show episodes<span class="sgicon-arrowdown" style="margin-left:4px"></span>'); })
tbl.on('show.bs.collapse', function () { btn.html('Hide episodes<span class="sgicon-arrowup" style="margin-left:4px"></span>'); })
});
#end raw
});
</script>
</div> </div>
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_bottom.tmpl')
#if None is not $has_art
#include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_livepanel.tmpl')
#end if
#include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_bottom.tmpl')

View file

@ -1,29 +1,32 @@
#import sickbeard #import sickbeard
#import lib.adba as adba #import lib.adba as adba
#from sickbeard import common #from sickbeard import (blackandwhitelist, common, exceptions, helpers, scene_exceptions)
#from sickbeard import exceptions
#from sickbeard import scene_exceptions
#from sickbeard.helpers import anon_url #from sickbeard.helpers import anon_url
#from sickbeard.indexers.indexer_config import INDEXER_TVDB <% def sg_var(varname, default=False): return getattr(sickbeard, varname, default) %>#slurp#
#import sickbeard.blackandwhitelist <% def sg_str(varname, default=''): return getattr(sickbeard, varname, default) %>#slurp#
## ##
#set global $title = 'Edit ' + $show.name #set global $title = 'Edit ' + $show.name
#set global $header = $show.name #set global $header = $show.name
#set global $sbPath = '..' #set global $sbPath = '..'
#set global $topmenu = 'home' #set global $topmenu = 'home'
#set global $page_body_attr = 'edit-show' #set $css = $getVar('css', 'reg')
#set $has_art = $getVar('has_art', None)
#set $restart = 'Restart SickGear for new features on this page'
#set $show_message = (None, $restart)[None is $has_art]
#set global $page_body_attr = 'edit-show" class="' + $css
## ##
#import os.path #import os.path
#from urllib import quote_plus #from urllib import quote_plus
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_top.tmpl') #include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_top.tmpl')
<script>
var config = {showLang: '$show.lang', showIsAnime: #echo ('!1','!0')[$show.is_anime]#}
</script>
<script type="text/javascript" src="$sbRoot/js/qualityChooser.js?v=$sbPID"></script> <script type="text/javascript" src="$sbRoot/js/qualityChooser.js?v=$sbPID"></script>
<script type="text/javascript" src="$sbRoot/js/editShow.js?v=$sbPID"></script> <script type="text/javascript" src="$sbRoot/js/editShow.js?v=$sbPID"></script>
<script> <script type="text/javascript" src="$sbRoot/js/livepanel.js?v=$sbPID"></script>
var config = {showLang: '$show.lang', showIsAnime: #echo ['!1','!0'][$show.is_anime]#}
</script>
#if $varExists('header') #if $varExists('header')
<h1 class="header"><span class="grey-text">Edit</span> $header</h1> <h1 class="header"><span class="grey-text">Edit&nbsp;</span>$header</h1>
#else #else
<h1 class="title">$title</h1> <h1 class="title">$title</h1>
#end if #end if
@ -31,6 +34,21 @@
## ##
#set $html_checked = ' checked="checked"' #set $html_checked = ' checked="checked"'
#set $html_disabled = ' disabled="disabled"' #set $html_disabled = ' disabled="disabled"'
<div id="background-container">
#if $has_art
<ul>
#for $k, ($image, $rating) in enumerate($fanart)
<li class="#echo ' '.join((x for x in ({10:'group', 20:'fave', 30:'avoid'}.get($rating, ''), ('', 'background first-load')[$start_image == $k]) if x)) #" style="background-image:url($sbRoot/showPoster/?show=$show.indexerid&which=fanart_$image)"></li>
#end for
</ul>
#end if
</div>
#if $show_message
<div class="alert alert-info">
$show_message
</div>
#end if
<div id="config"> <div id="config">
<div id="config-content" class="linefix container"> <div id="config-content" class="linefix container">
<form action="editShow" method="post" id="editShow" style="width:894px"> <form action="editShow" method="post" id="editShow" style="width:894px">
@ -48,20 +66,20 @@
<div class="field-pair"> <div class="field-pair">
<label for="paused"> <label for="paused">
<span class="component-title">Paused</span> <span class="component-title">Pause searching releases</span>
<span class="component-desc"> <span class="component-desc">
<input type="checkbox" name="paused" id="paused"#echo ('', $html_checked)[$show.paused]#> <input type="checkbox" name="paused" id="paused"#echo ('', $html_checked)[$show.paused]#>
<p>#echo ('enable to not', 'disable to')[$show.paused]# search or match releases for <b class="boldest grey-text">$show.name</b></p> <p>for <b class="boldest grey-text">$show.name</b></p>
</span> </span>
</label> </label>
</div> </div>
<div class="field-pair#if $sickbeard.SHOWLIST_TAGVIEW != 'custom'# hidden#end if#"> <div class="field-pair#if $sg_str('SHOWLIST_TAGVIEW') != 'custom'# hidden#end if#">
<label for="tag"> <label for="tag">
<span class="component-title">Group show under</span> <span class="component-title">Group show under</span>
<span class="component-desc"> <span class="component-desc">
<select name="tag" id="tag" class="form-control form-control-inline input-sm"> <select name="tag" id="tag" class="form-control form-control-inline input-sm">
#for $tag in $sickbeard.SHOW_TAGS: #for $tag in $sg_var('SHOW_TAGS', []):
<option value="$tag" #if $tag == $show.tag then 'selected="selected"' else ''#>$tag#echo ('', ' (default)')['Show List' == $tag]#</option> <option value="$tag" #if $tag == $show.tag then 'selected="selected"' else ''#>$tag#echo ('', ' (default)')['Show List' == $tag]#</option>
#end for #end for
</select> </select>
@ -72,9 +90,9 @@
<div class="field-pair"> <div class="field-pair">
<span class="label-container"> <span class="label-container">
<span class="component-title">Alternative show name(s)</span> <span class="component-title">Alternative release name(s)</span>
<span class="component-desc"> <span class="component-desc">
<input type="text" id="SceneName" class="form-control form-control-inline input-sm input200"> <input type="text" id="SceneName" class="form-control form-control-inline input-sm input200" placeholder="Enter one title here, then 'Add'">
<select id="SceneNameSeason" class="form-control form-control-inline input-sm input100" style="#echo ('visibility:hidden','float:left')[$show.anime]#"> <select id="SceneNameSeason" class="form-control form-control-inline input-sm input100" style="#echo ('visibility:hidden','float:left')[$show.anime]#">
<option value="-1">Series</option> <option value="-1">Series</option>
#if $show.anime: #if $show.anime:
@ -84,8 +102,8 @@
#end if #end if
</select> </select>
<input class="btn btn-inline" type="button" value="Add" id="addSceneName"> <input class="btn btn-inline" type="button" value="Add" id="addSceneName">
<p style="float:left">e.g. The Show, The Show (2016), The Show (US)</p> <p style="float:left"><span class="add-tip">Enter one.. </span>e.g. Show, Show (2016), or The Show (US)</p>
<p class="clear-left note">post-processing or searching may require an alternative if a "Show not found" error is reported</p> <p class="clear-left note">searching and post-processing require the alternatives if "Show not found" errors are in the logs</p>
</span> </span>
<span id="SceneException" class="component-desc" style="display:none"> <span id="SceneException" class="component-desc" style="display:none">
<h4 class="grey-text">Alternative a.k.a scene exceptions list (multi-selectable)</h4> <h4 class="grey-text">Alternative a.k.a scene exceptions list (multi-selectable)</h4>
@ -96,7 +114,7 @@
#end for #end for
#end for #end for
</select> </select>
<span><p class="note">#if $show.is_anime#S* = Any series. #end if#This case insensitive list overrides the original name to process</p></span> <span><p class="note">#if $show.is_anime#S* = Any series. #end if#The original name is used along<br />with this case insensitive list</p></span>
<div> <div>
<input id="removeSceneName" value="Remove" class="btn pull-left" type="button" style="margin-top: 10px;"/> <input id="removeSceneName" value="Remove" class="btn pull-left" type="button" style="margin-top: 10px;"/>
</div> </div>
@ -130,7 +148,7 @@
#set $qualities = $common.Quality.splitQuality(int($show.quality)) #set $qualities = $common.Quality.splitQuality(int($show.quality))
#set global $anyQualities = $qualities[0] #set global $anyQualities = $qualities[0]
#set global $bestQualities = $qualities[1] #set global $bestQualities = $qualities[1]
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_qualityChooser.tmpl') #include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_qualityChooser.tmpl')
#if $anyQualities + $bestQualities #if $anyQualities + $bestQualities
<div class="field-pair show-if-quality-custom" style="display:none"> <div class="field-pair show-if-quality-custom" style="display:none">
@ -213,7 +231,7 @@
#if $show.is_anime #if $show.is_anime
#import sickbeard.blackandwhitelist #import sickbeard.blackandwhitelist
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_blackwhitelist.tmpl') #include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_blackwhitelist.tmpl')
<script type="text/javascript" src="$sbRoot/js/blackwhite.js?v=$sbPID"></script> <script type="text/javascript" src="$sbRoot/js/blackwhite.js?v=$sbPID"></script>
#end if #end if
</div><!-- /component-group2 //--> </div><!-- /component-group2 //-->
@ -233,7 +251,7 @@
<label for="flatten_folders"> <label for="flatten_folders">
<span class="component-title">Flat folder hierarchy</span> <span class="component-title">Flat folder hierarchy</span>
<span class="component-desc"> <span class="component-desc">
<input type="checkbox" name="flatten_folders" id="flatten_folders"#echo ('', $html_checked)[$show.flatten_folders and not $sickbeard.NAMING_FORCE_FOLDERS]##echo ('', $html_disabled)[$sickbeard.NAMING_FORCE_FOLDERS]#> <input type="checkbox" name="flatten_folders" id="flatten_folders"#echo ('', $html_checked)[$show.flatten_folders and not $sg_var('NAMING_FORCE_FOLDERS')]##echo ('', $html_disabled)[$sg_var('NAMING_FORCE_FOLDERS')]#>
<p>prevent creating season folders to group files</p> <p>prevent creating season folders to group files</p>
</span> </span>
</label> </label>
@ -243,8 +261,27 @@
<label for="subtitles"> <label for="subtitles">
<span class="component-title">Subtitles</span> <span class="component-title">Subtitles</span>
<span class="component-desc"> <span class="component-desc">
<input type="checkbox" name="subtitles" id="subtitles"#echo ('', $html_checked)[$show.subtitles and $sickbeard.USE_SUBTITLES]##echo ($html_disabled, '')[$sickbeard.USE_SUBTITLES]#> <input type="checkbox" name="subtitles" id="subtitles"#echo ('', $html_checked)[$show.subtitles and $sg_var('USE_SUBTITLES')]##echo ($html_disabled, '')[$sg_var('USE_SUBTITLES')]#>
<p#if not $sickbeard.USE_SUBTITLES# class="grey-text"><del#end if#>download episode subtitles for this show#if not $sickbeard.USE_SUBTITLES#</del> ... (<span class="red-text">note: first <a href="$sbRoot/config/subtitles/">enable the subtitle system here</a></span>)#end if#</p> <p#if not $sg_var('USE_SUBTITLES')# class="grey-text"><del#end if#>download episode subtitles for this show#if not $sg_var('USE_SUBTITLES')#</del> ... (<span class="red-text">note: first <a href="$sbRoot/config/subtitles/">enable the subtitle system here</a></span>)#end if#</p>
</span>
</label>
</div>
<div class="field-pair">
<label for="reset_fanart">
<span class="component-title">Reset fanart ratings</span>
<span class="component-desc">
#if $num_ratings
<input type="checkbox" name="reset_fanart" id="reset_fanart">
<p>delete <span class="grey-text">$num_ratings</span> fanart rating$helpers.maybe_plural($num_ratings) for "<span class="grey-text">$show.name</span>"</p>
#else
<p>no fanart ratings to delete for "<span class="grey-text">$show.name</span>"</p>
#end if
<p>
<span class="grey-text">fanart usage:&nbsp;</span>maximum $sg_var('FANART_LIMIT', 3) fanart images downloaded per show, <a href="$sbRoot/config/general/#core-component-group2">change limit</a><br />
<span class="grey-text">fanart keys:&nbsp;</span>hold down Ctrl+Alt (mac: Command+Option) and then press any of... left or right to change image, and<br />
's' to change and save ratings where 'a'/down = avoid, 'f' = fave, 'g'/up = group (repeat keypress to toggle rating)
with the livepanel not in 's'ave mode; up = change view mode, down = toggle translucency
</span> </span>
</label> </label>
</div> </div>
@ -327,7 +364,7 @@
<p>for unlocked IDs</p> <p>for unlocked IDs</p>
</span> </span>
<span id="save-wait" class="component-desc hide"> <span id="save-wait" class="component-desc hide">
<span><img src="$sbRoot/images/loading16#echo ('', '-dark')['dark' == $sickbeard.THEME_NAME]#.gif" style="margin-right:6px">Saving...</span> <span><img src="$sbRoot/images/loading16#echo ('', '-dark')['dark' == $sg_str('THEME_NAME', 'dark')]#.gif" style="margin-right:6px">Saving...</span>
</span> </span>
</div> </div>
</div> </div>
@ -344,4 +381,4 @@
</div> </div>
</div> </div>
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_bottom.tmpl') #include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_bottom.tmpl')

View file

@ -4,41 +4,53 @@
#from sickbeard.common import * #from sickbeard.common import *
#from sickbeard import sbdatetime #from sickbeard import sbdatetime
#from sickbeard.helpers import anon_url #from sickbeard.helpers import anon_url
#from sickbeard.indexers.indexer_config import INDEXER_TVDB, INDEXER_IMDB
<% def sg_var(varname, default=False): return getattr(sickbeard, varname, default) %>#slurp#
<% def sg_str(varname, default=''): return getattr(sickbeard, varname, default) %>#slurp#
## ##
#set global $title = 'Episode View' #set global $title = 'Episode View'
#set global $header = 'Episode View' #set global $header = 'Episode View'
#set global $sbPath = '..' #set global $sbPath = '..'
#set global $topmenu = 'episodeView' #set global $topmenu = 'episodeView'
#set $css = $getVar('css', '')
#set $has_art = $getVar('has_art', None)
#set $restart = 'Restart SickGear for new features on this page'
#set $show_message = (None, $restart)[not $varExists('fanart')]
#set global $page_body_attr = 'episode-view" class="' + $css
## ##
#import os.path #import os.path
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_top.tmpl') #include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_top.tmpl')
#set $sort = $sickbeard.EPISODE_VIEW_SORT <script>
<!--
var config = {hasArt: #echo ('!0', '!1')[not $has_art]#}
//-->
</script>
#set $sort = $sg_var('EPISODE_VIEW_SORT')
#set $table_sort_header_codes = {'time': 0, 'show': 1, 'network': 4} #set $table_sort_header_codes = {'time': 0, 'show': 1, 'network': 4}
#if $sort not in $table_sort_header_codes: #if $sort not in $table_sort_header_codes
#set $sort = 'time' #set $sort = 'time'
#end if #end if
#if 'daybyday' != $layout: #if $layout in ['daybyday', 'list']
<script type="text/javascript" src="$sbRoot/js/ajaxEpSearch.js?v=$sbPID"></script>
#end if
#if $varExists('header')
<h1 class="header">$header</h1>
#else
<h1 class="title">$title</h1>
#end if
#if 'daybyday' == $layout:
<script type="text/javascript" src="$sbRoot/js/plotTooltip.js?v=$sbPID"></script> <script type="text/javascript" src="$sbRoot/js/plotTooltip.js?v=$sbPID"></script>
<script type="text/javascript" charset="utf-8"> #end if
#if 'daybyday' != $layout
<script type="text/javascript" src="$sbRoot/js/ajaxEpSearch.js?v=$sbPID"></script>
<input type="hidden" id="sbRoot" value="$sbRoot" />
#else
<script>
<!-- <!--
\$(document).ready(function(){ #raw
$(document).ready(function(){
$('#Carousel div[title], #Carousel span[title]').tooltip({placement: 'top', html: !0});
var \$container = []; $.sgDayContainer = [];
\$.each(\$('[id^=day]'), function(){\$container.push(\$('#' + \$(this).attr('id')))}); $.each($('[id^=day]'), function(){$.sgDayContainer.push($('#' + $(this).attr('id')))});
jQuery.each(\$container, function(j) { jQuery.each($.sgDayContainer, function(j) {
this.isotope({ this.isotope({
itemSelector: '.daybyday-show', itemSelector: '.daybyday-show',
sortBy: '$sort', sortBy: '$sort',
@ -46,21 +58,21 @@
transitionDuration: 0, transitionDuration: 0,
getSortData: { getSortData: {
network: function(itemElem) { network: function(itemElem) {
return \$(itemElem).attr('data-network') || ''; return $(itemElem).attr('data-network') || '';
}, },
showname: function(itemElem) { showname: function(itemElem) {
return \$(itemElem).attr('data-name') || ''; return $(itemElem).attr('data-name') || '';
}, },
season: function(itemElem) { season: function(itemElem) {
var season = \$(itemElem).attr('data-season') || '0'; var season = $(itemElem).attr('data-season') || '0';
return season.length && parseInt(season, 10); return season.length && parseInt(season, 10);
}, },
episode: function(itemElem) { episode: function(itemElem) {
var episode = \$(itemElem).attr('data-episode') || '0'; var episode = $(itemElem).attr('data-episode') || '0';
return episode.length && parseInt(episode, 10); return episode.length && parseInt(episode, 10);
}, },
time: function(itemElem) { time: function(itemElem) {
var time = \$(itemElem).attr('data-time') || '0'; var time = $(itemElem).attr('data-time') || '0';
return time.length && parseInt(time, 10); return time.length && parseInt(time, 10);
} }
} }
@ -68,12 +80,12 @@
}); });
imagesLoaded('.daybyday-show', function() { imagesLoaded('.daybyday-show', function() {
jQuery.each(\$container, function(j) { jQuery.each($.sgDayContainer, function(j) {
this.isotope('layout'); this.isotope('layout');
}); });
}); });
var uiSortBy = (function(sortBy) { $.sgUiSortBy = (function(sortBy) {
var sortCriteria; var sortCriteria;
switch (sortBy) { switch (sortBy) {
case 'network': case 'network':
@ -87,124 +99,167 @@
sortCriteria = ['time', 'showname', 'season', 'episode']; sortCriteria = ['time', 'showname', 'season', 'episode'];
break; break;
} }
jQuery.each(\$container, function(j) { jQuery.each($.sgDayContainer, function(j) {
this.isotope({ this.isotope({
sortBy: sortCriteria, sortBy: sortCriteria,
sortAscending: 'asc' == \$('#sort-dir').attr('data-sort-dir') sortAscending: 'asc' == $('#sort-dir').attr('data-sort-dir')
}); });
}); });
}); });
\$('#sort').on('change', function() { $('#sort').on('change', function() {
uiSortBy(this.value); $.sgUiSortBy(this.value);
\$.get(this.options[this.selectedIndex].getAttribute('data-sort')); $.get(this.options[this.selectedIndex].getAttribute('data-sort'));
}); });
\$('#sort-dir').on('click', function() { $('#sort-dir').on('click', function() {
var sortdir = \$(this).attr('data-sort-dir'), var sortdir = $(this).attr('data-sort-dir'),
newdir = ('asc' == sortdir ? 'desc' : 'asc'); newdir = ('asc' == sortdir ? 'desc' : 'asc');
\$(this).attr('data-sort-dir', newdir); $(this).attr('data-sort-dir', newdir);
\$(this).attr('title', 'Click to sort ' + sortdir + 'ending'); $(this).attr('title', 'Click to sort ' + sortdir + 'ending');
\$(this).removeClass(sortdir).addClass(newdir); $(this).removeClass(sortdir).addClass(newdir);
uiSortBy(\$('#sort').val()); $.sgUiSortBy($('#sort').val());
}); });
\$('.carousel').on('slide.bs.carousel', function () { $('.carousel').on('slide.bs.carousel', function () {
imagesLoaded('.daybyday-show', function() { imagesLoaded('.daybyday-show', function() {
jQuery.each(\$container, function(j) { jQuery.each($.sgDayContainer, function(j) {
this.isotope('layout'); $(this).isotope('layout');
}); });
}); });
}); });
\$('div[title!=""], span[title!=""]').qtip({style: {classes: 'qtip-rounded qtip-shadow'}, $('#card-layout').on('click', function(e) {
position: {viewport: \$(window), my: 'left center', adjust: {y: -10, x: 0}}, var states$ = $('#episode-view.daybyday'), isPortrait = states$.hasClass('portrait'),
show: {solo: true} state = isPortrait ? ['landscape', 'portrait'] : ['portrait', 'landscape'],
img = isPortrait ? ['poster', 'banner'] : ['banner', 'poster'],
old = img[0] + '_thumb', repl = img[1] + '_thumb',
cachedImg = $.SickGear.Root + '/images/' + repl + '.jpg',
tid, interval = 250, timeout = (5 * 1000)/interval;
states$.addClass(state[0]).removeClass(state[1]);
tid = setInterval(function() {
if (0 < $('.poster').find('img[src*="' + old + '"]').length) {
timeout--;
} else {
timeout = 0;
}
if (0 == timeout) {
clearInterval(tid);
$.each($('.poster').find('img[src*="' + cachedImg + '"]'), function() {
$(this).attr('src', $(this).attr('data-src-new')).removeAttr('data-src-new');
}); });
$.sgUiSortBy($('#sort').val());
$.get($.SickGear.Root + '/setEpisodeViewCards');
}
}, interval);
$.each($('.poster').find('img[src*="' + old + '"]'), function() {
$(this).attr('data-src-new', $(this).attr('src').replace(old, repl));
$(this).attr('src', cachedImg);
}); });
return !1;
});
});
#end raw
//--> //-->
</script> </script>
#end if #end if
<style type="text/css"> <style type="text/css">
#SubMenu {display:none} #SubMenu{display:none}
#if 'daybyday' == $layout: #if 'daybyday' == $layout
.ep-caret { .ep-caret{cursor:pointer; vertical-align:middle; margin-right:2px}
cursor: pointer; .asc{border-top:0; border-bottom:8px solid}
vertical-align: middle; .desc{border-top:8px solid; border-bottom:0}
margin-right: 2px;
}
.asc {
border-top: 0;
border-bottom: 8px solid;
}
.desc {
border-top: 8px solid;
border-bottom: 0;
}
#end if #end if
</style> </style>
#if $show_message
<div class="h2footer pull-right"> <div class="alert alert-info" style="margin:-40px 0 50px">
$show_message
</div>
#end if
#if $varExists('header')
<h1 class="header" style="margin-bottom:0">$header</h1>
#else
<h1 class="title" style="margin-bottom:0">$title</h1>
#end if
#set $selected = ' selected="selected"'
<div id="HomeLayout" class="pull-right">
<div id="top-row">
<span>Layout <span>Layout
<select name="layout" class="form-control form-control-inline input-sm" onchange="location = this.options[this.selectedIndex].value;"> <select name="layout" class="form-control form-control-inline input-sm" onchange="location = this.options[this.selectedIndex].value;">
<option value="$sbRoot/setEpisodeViewLayout/?layout=banner" #if 'banner' == $sickbeard.EPISODE_VIEW_LAYOUT then 'selected="selected"' else ''#>Banner</option> <option value="$sbRoot/setEpisodeViewLayout/?layout=banner" #if 'banner' == $sg_str('EPISODE_VIEW_LAYOUT')#$selected#end if#>Banner</option>
<option value="$sbRoot/setEpisodeViewLayout/?layout=daybyday" #if 'daybyday' == $sickbeard.EPISODE_VIEW_LAYOUT then 'selected="selected"' else ''#>Day by Day</option> <option value="$sbRoot/setEpisodeViewLayout/?layout=daybyday" #if 'daybyday' == $sg_str('EPISODE_VIEW_LAYOUT', 'daybyday')#$selected#end if#>Day by Day</option>
<option value="$sbRoot/setEpisodeViewLayout/?layout=list" #if 'list' == $sickbeard.EPISODE_VIEW_LAYOUT then 'selected="selected"' else ''#>List</option> <option value="$sbRoot/setEpisodeViewLayout/?layout=list" #if 'list' == $sg_str('EPISODE_VIEW_LAYOUT')#$selected#end if#>List</option>
<option value="$sbRoot/setEpisodeViewLayout/?layout=poster" #if 'poster' == $sickbeard.EPISODE_VIEW_LAYOUT then 'selected="selected"' else ''#>Poster</option> <option value="$sbRoot/setEpisodeViewLayout/?layout=poster" #if 'poster' == $sg_str('EPISODE_VIEW_LAYOUT')#$selected#end if#>Poster</option>
</select> </select>
</span> </span>
&nbsp; &nbsp;
<span>Sort <span>Sort
#if 'daybyday' == $layout: #if 'daybyday' == $layout
<span id="sort-dir" data-sort-dir="asc" class="caret ep-caret asc" title="Click to sort descending">&nbsp;</span> <span id="sort-dir" data-sort-dir="asc" class="caret ep-caret asc" title="Click to sort descending">&nbsp;</span>
#end if #end if
By By
#if 'daybyday' == $layout: #if 'daybyday' == $layout
<select name="sort" id="sort" class="form-control form-control-inline input-sm"> <select name="sort" id="sort" class="form-control form-control-inline input-sm">
<option value="network" data-sort="$sbRoot/setEpisodeViewSort/?sort=network&redir=0" #if 'network' == $sort then 'selected="selected"' else ''#>Network</option> <option value="network" data-sort="$sbRoot/setEpisodeViewSort/?sort=network&redir=0" #if 'network' == $sort#$selected#end if#>Network</option>
<option value="show" data-sort="$sbRoot/setEpisodeViewSort/?sort=show&redir=0" #if 'show' == $sort then 'selected="selected"' else ''#>Show</option> <option value="show" data-sort="$sbRoot/setEpisodeViewSort/?sort=show&redir=0" #if 'show' == $sort#$selected#end if#>Show</option>
<option value="time" data-sort="$sbRoot/setEpisodeViewSort/?sort=time&redir=0" #if 'time' == $sort then 'selected="selected"' else ''#>Time</option> <option value="time" data-sort="$sbRoot/setEpisodeViewSort/?sort=time&redir=0" #if 'time' == $sort#$selected#end if#>Time</option>
#else #else
<select name="sort" class="form-control form-control-inline input-sm" onchange="location = this.options[this.selectedIndex].value;"> <select name="sort" class="form-control form-control-inline input-sm" onchange="location = this.options[this.selectedIndex].value;">
<option value="$sbRoot/setEpisodeViewSort/?sort=time" #if 'time' == $sort then 'selected="selected"' else ''#>Date/Time</option> <option value="$sbRoot/setEpisodeViewSort/?sort=time" #if 'time' == $sort#$selected#end if#>Date/Time</option>
<option value="$sbRoot/setEpisodeViewSort/?sort=network" #if 'network' == $sort then 'selected="selected"' else ''#>Network</option> <option value="$sbRoot/setEpisodeViewSort/?sort=network" #if 'network' == $sort#$selected#end if#>Network</option>
<option value="$sbRoot/setEpisodeViewSort/?sort=show" #if 'show' == $sort then 'selected="selected"' else ''#>Show</option> <option value="$sbRoot/setEpisodeViewSort/?sort=show" #if 'show' == $sort#$selected#end if#>Show</option>
#end if #end if
</select> </select>
</span> </span>
&nbsp; &nbsp;
<span>View Paused <span class="no-marginr">View Paused
<select name="viewpaused" class="form-control form-control-inline input-sm" onchange="location = this.options[this.selectedIndex].value;"> <select name="viewpaused" class="form-control form-control-inline input-sm" onchange="location = this.options[this.selectedIndex].value;" style="margin-bottom:10px">
<option value="$sbRoot/toggleEpisodeViewDisplayPaused"<%= (' selected="selected"', '')[True == sickbeard.EPISODE_VIEW_DISPLAY_PAUSED] %>>Hidden</option> <option value="$sbRoot/toggleEpisodeViewDisplayPaused"#if not $sg_var('EPISODE_VIEW_DISPLAY_PAUSED')#$selected#end if#>Hidden</option>
<option value="$sbRoot/toggleEpisodeViewDisplayPaused"<%= ('', ' selected="selected"')[True == sickbeard.EPISODE_VIEW_DISPLAY_PAUSED] %>>Shown</option> <option value="$sbRoot/toggleEpisodeViewDisplayPaused"#if $sg_var('EPISODE_VIEW_DISPLAY_PAUSED')#$selected#end if#>Shown</option>
</select> </select>
</span> </span>
</div> </div>
<div class="key pull-right"> <div class="key pull-right">
#if 'daybyday' != $layout: #if 'daybyday' != $layout
<b>Key:</b> <b>Key:</b>
<span class="listing-key listing-overdue">Missed</span> <span class="listing-key listing-overdue">Missed</span>
<span class="listing-key listing-current">Current</span> <span class="listing-key listing-current">Current</span>
<span class="listing-key listing-default">Future</span> <span class="listing-key listing-default">Future</span>
<span class="listing-key listing-toofar">Distant</span> <span class="listing-key listing-toofar">Distant</span>
#end if
#if 'daybyday' == $layout
<a id="card-layout" class="btn btn-inline" name="">
<span id="landscape">
<i class="sgicon-img-landscape"></i> Collapse Cards
</span>
<span id="portrait">
<i class="sgicon-img-portrait"></i> Expand Cards
</span>
</a>
#end if #end if
<a class="btn btn-inline forceBacklog" href="webcal://$sbHost:$sbHttpPort/calendar"> <a class="btn btn-inline forceBacklog" href="webcal://$sbHost:$sbHttpPort/calendar">
<i class="sgicon-rss"></i> Subscribe</a> <i class="sgicon-rss"></i> Subscribe</a>
</div> </div>
</div>
<br>
#if 'list' == $layout
#if 'list' == $layout:
<!-- start list view //--> <!-- start list view //-->
<script type="text/javascript" src="$sbRoot/js/plotTooltip.js?v=$sbPID"></script> <script>
<script type="text/javascript" charset="utf-8">
<!-- <!--
\$.tablesorter.addParser({ #raw
$.tablesorter.addParser({
id: 'loadingNames', id: 'loadingNames',
is: function(s) { is: function(s) {
return false return false
@ -216,7 +271,7 @@
}, },
type: 'text' type: 'text'
}); });
\$.tablesorter.addParser({ $.tablesorter.addParser({
id: 'quality', id: 'quality',
is: function(s) { is: function(s) {
return false return false
@ -226,7 +281,7 @@
}, },
type: 'numeric' type: 'numeric'
}); });
\$.tablesorter.addParser({ $.tablesorter.addParser({
id: 'cDate', id: 'cDate',
is: function(s) { is: function(s) {
return false return false
@ -237,18 +292,18 @@
type: 'numeric' type: 'numeric'
}); });
\$(document).ready(function(){ $(document).ready(function(){
sortList = [[$table_sort_header_codes[$sort], 0]]; sortList = [[$table_sort_header_codes[$sort], 0]];
\$('#showListTable:has(tbody tr)').tablesorter({ $('#showListTable:has(tbody tr)').tablesorter({
widgets: ['stickyHeaders'], widgets: ['stickyHeaders'],
sortList: sortList, sortList: sortList,
textExtraction: { textExtraction: {
0: function(node) {return \$(node).find('span').text().toLowerCase() || ''}, 0: function(node) {return $(node).find('span').text().toLowerCase() || ''},
1: function(node) {return \$(node).find('a').attr('data-name') || ''}, 1: function(node) {return $(node).find('a').attr('data-name') || ''},
4: function(node) {return \$(node).find('span').attr('data-network') || ''}, 4: function(node) {return $(node).find('span').attr('data-network') || ''},
5: function(node) {return \$(node).find('span').text().toLowerCase() || ''} 5: function(node) {return $(node).find('span').text().toLowerCase() || ''}
}, },
headers: { headers: {
0: {sorter: 'cDate'}, 0: {sorter: 'cDate'},
@ -263,16 +318,17 @@
} }
}); });
\$('#sbRoot').ajaxEpSearch(); $('#sbRoot').ajaxEpSearch();
#end raw
#set $fuzzydate = 'airdate' #set $fuzzydate = 'airdate'
#if $sickbeard.FUZZY_DATING: #if $sg_var('FUZZY_DATING')
fuzzyMoment({ fuzzyMoment({
containerClass: '.${fuzzydate}', containerClass: '.${fuzzydate}',
dateHasTime: !0, dateHasTime: !0,
dateFormat: '${sickbeard.DATE_PRESET}', dateFormat: '$sg_str('DATE_PRESET', '%x')',
timeFormat: '${sickbeard.TIME_PRESET}', timeFormat: '$sg_str('TIME_PRESET', '%I:%M %p')',
trimZero: #echo ('!1', '!0')[$sickbeard.TRIM_ZERO]# trimZero: #echo ('!1', '!0')[$sg_var('TRIM_ZERO')]#
}); });
#end if #end if
@ -282,9 +338,7 @@
#set $show_div = 'listing-default' #set $show_div = 'listing-default'
<input type="hidden" id="sbRoot" value="$sbRoot" /> <table id="showListTable" class="sickbeardTable tablesorter" cellspacing="1" border="0" cellpadding="0">
<table id="showListTable" class="sickbeardTable tablesorter seasonstyle" cellspacing="1" border="0" cellpadding="0">
<thead> <thead>
<tr> <tr>
@ -299,29 +353,29 @@
</tr> </tr>
</thead> </thead>
<tbody style="text-shadow:none;"> <tbody style="text-shadow:none">
#for $cur_result in $sql_results: #for $cur_result in $sql_results
#set $cur_indexer = int($cur_result['indexer']) #set $cur_indexer = int($cur_result['indexer'])
#set $runtime = $cur_result['runtime'] #set $runtime = $cur_result['runtime']
#set $display_name = (re.sub('^((?:A(?!\s+to)n?)|The)\s(\w)', r'<span class="article">\1</span> \2', $cur_result['show_name']), $cur_result['show_name'])[$sickbeard.SORT_ARTICLE] #set $display_name = (re.sub('^((?:A(?!\s+to)n?)|The)\s(\w)', r'<span class="article">\1</span> \2', $cur_result['show_name']), $cur_result['show_name'])[$sg_var('SORT_ARTICLE')]
#if int($cur_result['paused']) and not $sickbeard.EPISODE_VIEW_DISPLAY_PAUSED: #if int($cur_result['paused']) and not $sg_var('EPISODE_VIEW_DISPLAY_PAUSED')
#continue #continue
#end if #end if
#set $cur_ep_airdate = $cur_result['localtime'].date() #set $cur_ep_airdate = $cur_result['localtime'].date()
#if $runtime: #if $runtime
#set $cur_ep_enddate = $cur_result['localtime'] + datetime.timedelta(minutes = $runtime) #set $cur_ep_enddate = $cur_result['localtime'] + datetime.timedelta(minutes = $runtime)
#if $cur_ep_enddate < $today: #if $cur_ep_enddate < $today
#set $show_div = 'listing-overdue' #set $show_div = 'listing-overdue'
#elif $cur_ep_airdate >= $next_week.date(): #elif $cur_ep_airdate >= $next_week.date()
#set $show_div = 'listing-toofar' #set $show_div = 'listing-toofar'
#elif $cur_ep_airdate >= $today.date() and $cur_ep_airdate < $next_week.date(): #elif $cur_ep_airdate >= $today.date() and $cur_ep_airdate < $next_week.date()
#if $cur_ep_airdate == $today.date(): #if $cur_ep_airdate == $today.date()
#set $show_div = 'listing-current' #set $show_div = 'listing-current'
#else: #else
#set $show_div = 'listing-default' #set $show_div = 'listing-default'
#end if #end if
#end if #end if
@ -336,7 +390,7 @@
</td> </td>
<td class="tvShow"><a href="$sbRoot/home/displayShow?show=${cur_result['showid']}" data-name="$cur_result['data_show_name']">$display_name</a> <td class="tvShow"><a href="$sbRoot/home/displayShow?show=${cur_result['showid']}" data-name="$cur_result['data_show_name']">$display_name</a>
#if int($cur_result['paused']): #if int($cur_result['paused'])
<span class="pause">[paused]</span> <span class="pause">[paused]</span>
#end if #end if
</td> </td>
@ -346,10 +400,10 @@
</td> </td>
<td> <td>
#if $cur_result['description']: #if $cur_result['description']
<img alt="" src="$sbRoot/images/info32.png" height="16" width="16" class="plotInfo" id="plot-${show_id}" /> <img alt="" src="$sbRoot/images/info32.png" height="16" width="16" class="plotInfo" id="plot-${show_id}" />
#else: #else
<img alt="" src="$sbRoot/images/info32.png" width="16" height="16" class="plotInfoNone" /> <img alt="" src="$sbRoot/images/info32.png" width="16" height="16" class="plotInfoNone opacity40" />
#end if #end if
$cur_result['name'] $cur_result['name']
</td> </td>
@ -359,16 +413,16 @@
</td> </td>
<td align="center"> <td align="center">
#if int($cur_result['quality']) in $qualityPresets: #if int($cur_result['quality']) in $qualityPresets
<span class="quality $qualityPresetStrings[int($cur_result['quality'])]">$qualityPresetStrings[int($cur_result['quality'])]</span> <span class="quality $qualityPresetStrings[int($cur_result['quality'])]">$qualityPresetStrings[int($cur_result['quality'])]</span>
#else: #else
<span class="quality Custom">Custom</span> <span class="quality Custom">Custom</span>
#end if #end if
</td> </td>
<td align="center" style="vertical-align:middle"> <td align="center" style="vertical-align:middle">
#if sickbeard.USE_IMDB_INFO and $cur_result['imdb_id']: #if $sg_var('USE_IMDB_INFO') and $cur_result['imdb_id']
<a href="<%= anon_url('http://www.imdb.com/title/', cur_result['imdb_id']) %>" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false" title="http://www.imdb.com/title/${cur_result['imdb_id']}"><img alt="[imdb]" height="16" width="16" src="$sbRoot/images/imdb.png" /></a> <a href="<%= anon_url('http://www.imdb.com/title/', cur_result['imdb_id']) %>" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false" title="http://www.imdb.com/title/${cur_result['imdb_id']}"><img alt="[$sickbeard.indexerApi(INDEXER_IMDB).config.get('name')]" height="16" width="16" src="$sbRoot/images/$sickbeard.indexerApi(INDEXER_IMDB).config.get('icon')" /></a>
#end if #end if
<a href="<%= anon_url(sickbeard.indexerApi(cur_indexer).config['show_url'], cur_result['showid']) %>" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false" title="$sickbeard.indexerApi($cur_indexer).config['show_url']${cur_result['showid']}"><img alt="$sickbeard.indexerApi($cur_indexer).name" height="16" width="16" src="$sbRoot/images/$sickbeard.indexerApi($cur_indexer).config['icon']" /></a> <a href="<%= anon_url(sickbeard.indexerApi(cur_indexer).config['show_url'], cur_result['showid']) %>" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false" title="$sickbeard.indexerApi($cur_indexer).config['show_url']${cur_result['showid']}"><img alt="$sickbeard.indexerApi($cur_indexer).name" height="16" width="16" src="$sbRoot/images/$sickbeard.indexerApi($cur_indexer).config['icon']" /></a>
</td> </td>
@ -394,32 +448,34 @@
#else if $layout in ['banner', 'poster']: #else if $layout in ['banner', 'poster']
<!-- start non list view //--> <!-- start non list view //-->
<script type="text/javascript" charset="utf-8"> <script>
<!-- <!--
\$(document).ready(function(){ #raw
\$('#sbRoot').ajaxEpSearch({'size': 16, 'loadingImage': 'loading16' + themeSpinner + '.gif'}); $(document).ready(function(){
\$('.ep_summary').hide(); $('#sbRoot').ajaxEpSearch({'size': 16, 'loadingImage': 'loading16' + themeSpinner + '.gif'});
\$('.ep_summaryTrigger').click(function() { $('.ep_summary').hide();
\$(this).next('.ep_summary').slideToggle('normal', function() { $('.ep_summaryTrigger').click(function() {
\$(this).prev('.ep_summaryTrigger').attr('src', function(i, src) { $(this).next('.ep_summary').slideToggle('normal', function() {
return \$(this).next('.ep_summary').is(':visible') ? src.replace('plus','minus') : src.replace('minus','plus') $(this).prev('.ep_summaryTrigger').attr('src', function(i, src) {
return $(this).next('.ep_summary').is(':visible') ? src.replace('plus','minus') : src.replace('minus','plus')
}); });
}); });
}); });
#end raw
#set $fuzzydate = 'airdate' #set $fuzzydate = 'airdate'
#if $sickbeard.FUZZY_DATING: #if $sg_var('FUZZY_DATING')
fuzzyMoment({ fuzzyMoment({
dtInline: !0, dtInline: !0,
dtGlue: ' at ', dtGlue: ' at ',
containerClass: '.${fuzzydate}', containerClass: '.${fuzzydate}',
dateHasTime: !0, dateHasTime: !0,
dateFormat: '${sickbeard.DATE_PRESET}', dateFormat: '$sg_str('DATE_PRESET', '%x')',
timeFormat: '${sickbeard.TIME_PRESET}', timeFormat: '$sg_str('TIME_PRESET', '%I:%M %p')',
trimZero: #echo ('!1', '!0')[$sickbeard.TRIM_ZERO]# trimZero: #echo ('!1', '!0')[$sg_var('TRIM_ZERO')]#
}); });
#end if #end if
}); });
@ -432,112 +488,107 @@
#set $today_header = False #set $today_header = False
#set $show_div = 'ep_listing listing-default' #set $show_div = 'ep_listing listing-default'
#if 'show' == $sort: <div style="clear:both">
<br /><br /> #for $x, $cur_result in $enumerate($sql_results)
#end if #set $add_space = ('', ' add-space')[bool($x)]
#for $cur_result in $sql_results:
#set $cur_indexer = int($cur_result['indexer']) #set $cur_indexer = int($cur_result['indexer'])
#set $display_name = (re.sub('^((?:A(?!\s+to)n?)|The)\s(\w)', r'<span class="article">\1</span> \2', $cur_result['show_name']), $cur_result['show_name'])[$sickbeard.SORT_ARTICLE] #set $display_name = (re.sub('^((?:A(?!\s+to)n?)|The)\s(\w)', r'<span class="article">\1</span> \2', $cur_result['show_name']), $cur_result['show_name'])[$sg_var('SORT_ARTICLE')]
##
#if int($cur_result['paused']) and not $sickbeard.EPISODE_VIEW_DISPLAY_PAUSED: #if int($cur_result['paused']) and not $sg_var('EPISODE_VIEW_DISPLAY_PAUSED')
#continue #continue
#end if #end if
##
#set $runtime = $cur_result['runtime'] #set $runtime = $cur_result['runtime']
##
#if 'network' == $sort: #if 'network' == $sort
##
#set $show_network = $cur_result['network'] if $cur_result['network'] else 'no network' #set $show_network = $cur_result['network'] if $cur_result['network'] else 'no network'
#if $cur_segment != $show_network: #if $cur_segment != $show_network
<div class="episode-view-header">
<br><h2 class="network">$show_network</h2>
#set $cur_segment = $cur_result['network'] #set $cur_segment = $cur_result['network']
<h2 class="network$add_space">$show_network</h2>
#end if #end if
#set $cur_ep_airdate = $cur_result['localtime'].date() #set $cur_ep_airdate = $cur_result['localtime'].date()
##
#if $runtime: #if $runtime
#set $cur_ep_enddate = $cur_result['localtime'] + datetime.timedelta(minutes = $runtime) #set $cur_ep_enddate = $cur_result['localtime'] + datetime.timedelta(minutes = $runtime)
#if $cur_ep_enddate < $today: #if $cur_ep_enddate < $today
#set $show_div = 'ep_listing listing-overdue' #set $show_div = 'ep_listing listing-overdue'
#elif $cur_ep_airdate >= $next_week.date(): #elif $cur_ep_airdate >= $next_week.date()
#set $show_div = 'ep_listing listing-toofar' #set $show_div = 'ep_listing listing-toofar'
#elif $cur_ep_enddate >= $today and $cur_ep_airdate < $next_week.date(): #elif $cur_ep_enddate >= $today and $cur_ep_airdate < $next_week.date()
#if $cur_ep_airdate == $today.date(): #if $cur_ep_airdate == $today.date()
#set $show_div = 'ep_listing listing-current' #set $show_div = 'ep_listing listing-current'
#else: #else
#set $show_div = 'ep_listing listing-default' #set $show_div = 'ep_listing listing-default'
#end if #end if
#end if #end if
#end if #end if
#elif 'time' == $sort
#elif 'time' == $sort: ##
#set $cur_ep_airdate = $cur_result['localtime'].date() #set $cur_ep_airdate = $cur_result['localtime'].date()
##
#if $cur_segment != $cur_ep_airdate: #if $cur_segment != $cur_ep_airdate
#if $runtime: #if $runtime
#set $cur_ep_enddate = $cur_result['localtime'] + datetime.timedelta(minutes = $runtime) #set $cur_ep_enddate = $cur_result['localtime'] + datetime.timedelta(minutes = $runtime)
#if $cur_ep_enddate < $today and $cur_ep_airdate != $today.date() and not $missed_header: #if $cur_ep_enddate < $today and $cur_ep_airdate != $today.date() and not $missed_header
<br /><h2 class="day">Missed</h2> <h2 class="day">Missed</h2>
#set $missed_header = True #set $missed_header = True
#elif $cur_ep_airdate >= $next_week.date() and not $too_late_header: #elif $cur_ep_airdate >= $next_week.date() and not $too_late_header
<br /><h2 class="day">Later</h2> <h2 class="day">Later</h2>
#set $too_late_header = True #set $too_late_header = True
#elif $cur_ep_enddate >= $today and $cur_ep_airdate < $next_week.date(): #elif $cur_ep_enddate >= $today and $cur_ep_airdate < $next_week.date()
#if $cur_ep_airdate == $today.date(): #if $cur_ep_airdate == $today.date()
<br /><h2 class="day">$sbdatetime.sbdatetime.sbfdate($cur_ep_airdate, '%A').decode($sickbeard.SYS_ENCODING).capitalize() <span style="font-size: 14px; vertical-align: top;">[Today]</span></h2> <h2 class="day">$sbdatetime.sbdatetime.sbfdate($cur_ep_airdate, '%A').decode($sickbeard.SYS_ENCODING).capitalize() <span style="font-size:14px; vertical-align:top">[Today]</span></h2>
#set $today_header = True #set $today_header = True
#else: #else
<br /><h2 class="day">$sbdatetime.sbdatetime.sbfdate($cur_ep_airdate, '%A').decode($sickbeard.SYS_ENCODING).capitalize()</h2> <h2 class="day">$sbdatetime.sbdatetime.sbfdate($cur_ep_airdate, '%A').decode($sickbeard.SYS_ENCODING).capitalize()</h2>
#end if #end if
#end if #end if
#end if #end if
#set $cur_segment = $cur_ep_airdate #set $cur_segment = $cur_ep_airdate
#end if #end if
##
#if $cur_ep_airdate == $today.date() and not $today_header: #if $cur_ep_airdate == $today.date() and not $today_header
<div class="episode-view-header"> <h2 class="day">$sbdatetime.sbdatetime.sbfdate($cur_ep_airdate, '%A').decode($sickbeard.SYS_ENCODING).capitalize() <span style="font-size:14px; vertical-align:top">[Today]</span></h2>
<br /><h2 class="day">$sbdatetime.sbdatetime.sbfdate($cur_ep_airdate, '%A').decode($sickbeard.SYS_ENCODING).capitalize() <span style="font-size: 14px; vertical-align: top;">[Today]</span></h2>
#set $today_header = True #set $today_header = True
#end if #end if
##
#if $runtime: #if $runtime
#set $cur_ep_enddate = $cur_result['localtime'] + datetime.timedelta(minutes = $runtime) #set $cur_ep_enddate = $cur_result['localtime'] + datetime.timedelta(minutes = $runtime)
#if $cur_ep_enddate < $today: #if $cur_ep_enddate < $today
#set $show_div = 'ep_listing listing-overdue' #set $show_div = 'ep_listing listing-overdue'
#elif $cur_ep_airdate >= $next_week.date(): #elif $cur_ep_airdate >= $next_week.date()
#set $show_div = 'ep_listing listing-toofar' #set $show_div = 'ep_listing listing-toofar'
#elif $cur_ep_enddate >= $today and $cur_ep_airdate < $next_week.date(): #elif $cur_ep_enddate >= $today and $cur_ep_airdate < $next_week.date()
#if $cur_ep_airdate == $today.date(): #if $cur_ep_airdate == $today.date()
#set $show_div = 'ep_listing listing-current' #set $show_div = 'ep_listing listing-current'
#else: #else
#set $show_div = 'ep_listing listing-default' #set $show_div = 'ep_listing listing-default'
#end if #end if
#end if #end if
#end if #end if
#elif 'show' == $sort: #elif 'show' == $sort
#set $cur_ep_airdate = $cur_result['localtime'].date() #set $cur_ep_airdate = $cur_result['localtime'].date()
#slurp
#if $runtime: #if $runtime
#set $cur_ep_enddate = $cur_result['localtime'] + datetime.timedelta(minutes = $runtime) #set $cur_ep_enddate = $cur_result['localtime'] + datetime.timedelta(minutes = $runtime)
#if $cur_ep_enddate < $today: #if $cur_ep_enddate < $today
#set $show_div = 'ep_listing listing-overdue listingradius' #set $show_div = 'ep_listing listing-overdue listingradius'
#elif $cur_ep_airdate >= $next_week.date(): #elif $cur_ep_airdate >= $next_week.date()
#set $show_div = 'ep_listing listing-toofar listingradius' #set $show_div = 'ep_listing listing-toofar listingradius'
#elif $cur_ep_enddate >= $today and $cur_ep_airdate < $next_week.date(): #elif $cur_ep_enddate >= $today and $cur_ep_airdate < $next_week.date()
#if $cur_ep_airdate == $today.date(): #if $cur_ep_airdate == $today.date()
#set $show_div = 'ep_listing listing-current listingradius' #set $show_div = 'ep_listing listing-current listingradius'
#else: #else
#set $show_div = 'ep_listing listing-default listingradius' #set $show_div = 'ep_listing listing-default listingradius'
#end if #end if
#end if #end if
#end if #end if
#end if #end if
#slurp
<!-- start $cur_result['show_name'] //--> <!-- start $cur_result['show_name'] //-->
<div class="$show_div" id="listing-${cur_result['showid']}"> <div class="$show_div" id="listing-${cur_result['showid']}">
<div class="tvshowDiv"> <div class="tvshowDiv">
<table width="100%" border="0" cellpadding="0" cellspacing="0"> <table width="100%" border="0" cellpadding="0" cellspacing="0">
<tr> <tr>
@ -545,23 +596,22 @@
<a href="$sbRoot/home/displayShow?show=${cur_result['showid']}"><img alt="" class="#if 'banner' == $layout then 'bannerThumb' else 'posterThumb'#" src="$sbRoot/showPoster/?show=${cur_result['showid']}&amp;which=#if 'poster' == $layout then 'poster_thumb' else $layout#" /></a> <a href="$sbRoot/home/displayShow?show=${cur_result['showid']}"><img alt="" class="#if 'banner' == $layout then 'bannerThumb' else 'posterThumb'#" src="$sbRoot/showPoster/?show=${cur_result['showid']}&amp;which=#if 'poster' == $layout then 'poster_thumb' else $layout#" /></a>
</th> </th>
#if 'banner' == $layout: #if 'banner' == $layout
</tr> </tr>
<tr> <tr>
#end if #end if
<td class="next_episode"> <td class="next_episode">
<div class="clearfix"> <div class="clearfix">
<span class="tvshowTitle"> <span class="tvshowTitle">
<a href="$sbRoot/home/displayShow?show=${cur_result['showid']}" data-name="$cur_result['data_show_name']">$display_name <a href="$sbRoot/home/displayShow?show=${cur_result['showid']}" data-name="$cur_result['data_show_name']">$display_name
#if int($cur_result['paused']): #if int($cur_result['paused'])
<span class="pause">[paused]</span> <span class="pause">[paused]</span>
#end if #end if
</a></span> </a></span>
<span class="tvshowTitleIcons"> <span class="tvshowTitleIcons">
#if sickbeard.USE_IMDB_INFO and $cur_result['imdb_id']: #if $sg_var('USE_IMDB_INFO') and $cur_result['imdb_id']
<a href="<%= anon_url('http://www.imdb.com/title/', cur_result['imdb_id']) %>" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false" title="http://www.imdb.com/title/${cur_result['imdb_id']}"><img alt="[imdb]" height="16" width="16" src="$sbRoot/images/imdb.png" /> <a href="<%= anon_url('http://www.imdb.com/title/', cur_result['imdb_id']) %>" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false" title="http://www.imdb.com/title/${cur_result['imdb_id']}"><img alt="[$sickbeard.indexerApi(INDEXER_IMDB).name]" height="16" width="16" src="$sbRoot/images/$sickbeard.indexerApi(INDEXER_IMDB).config.get('icon')" /></a>
#end if #end if
<a href="<%= anon_url(sickbeard.indexerApi(cur_indexer).config['show_url'], cur_result['showid']) %>" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false" title="$sickbeard.indexerApi($cur_indexer).config['show_url']${cur_result['showid']}"><img alt="$sickbeard.indexerApi($cur_indexer).name" height="16" width="16" src="$sbRoot/images/$sickbeard.indexerApi($cur_indexer).config['icon']" /></a> <a href="<%= anon_url(sickbeard.indexerApi(cur_indexer).config['show_url'], cur_result['showid']) %>" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false" title="$sickbeard.indexerApi($cur_indexer).config['show_url']${cur_result['showid']}"><img alt="$sickbeard.indexerApi($cur_indexer).name" height="16" width="16" src="$sbRoot/images/$sickbeard.indexerApi($cur_indexer).config['icon']" /></a>
<span><a href="$sbRoot/home/searchEpisode?show=${cur_result['showid']}&amp;season=$cur_result['season']&amp;episode=$cur_result['episode']" title="Manual Search" id="forceUpdate-${cur_result['showid']}" class="epSearch forceUpdate"><img alt="[search]" height="16" width="16" src="$sbRoot/images/search16.png" id="forceUpdateImage-${cur_result['showid']}" /></a></span> <span><a href="$sbRoot/home/searchEpisode?show=${cur_result['showid']}&amp;season=$cur_result['season']&amp;episode=$cur_result['episode']" title="Manual Search" id="forceUpdate-${cur_result['showid']}" class="epSearch forceUpdate"><img alt="[search]" height="16" width="16" src="$sbRoot/images/search16.png" id="forceUpdateImage-${cur_result['showid']}" /></a></span>
@ -571,28 +621,27 @@
<span class="title">Next Episode:</span> <span><%= 'S%02iE%02i' % (int(cur_result['season']), int(cur_result['episode'])) %> - $cur_result['name']</span> <span class="title">Next Episode:</span> <span><%= 'S%02iE%02i' % (int(cur_result['season']), int(cur_result['episode'])) %> - $cur_result['name']</span>
<div class="clearfix"> <div class="clearfix">
<span class="title">Airdate: </span><span class="${fuzzydate}">$sbdatetime.sbdatetime.sbfdatetime($cur_result['localtime']).decode($sickbeard.SYS_ENCODING)</span><%= ('', '<span> on %s</span>' % str(cur_result['network']))[None is not cur_result['network']] %> <span class="title">Airdate: </span><span class="${fuzzydate}">$sbdatetime.sbdatetime.sbfdatetime($cur_result['localtime']).decode($sickbeard.SYS_ENCODING)</span><%= ('', '<span> on %s</span>' % str(cur_result['network']))[None is not cur_result['network']] %>
</div> </div>
<div class="clearfix"> <div class="clearfix">
<span class="title">Quality:</span> <span class="title">Quality:</span>
#if int($cur_result['quality']) in $qualityPresets: #if int($cur_result['quality']) in $qualityPresets
<span class="quality $qualityPresetStrings[int($cur_result['quality'])]">$qualityPresetStrings[int($cur_result['quality'])]</span> <span class="quality $qualityPresetStrings[int($cur_result['quality'])]">$qualityPresetStrings[int($cur_result['quality'])]</span>
#else: #else
<span class="quality Custom">Custom</span> <span class="quality Custom">Custom</span>
#end if #end if
</div> </div>
</td> </td>
</tr> </tr>
<tr> <tr>
<td style="vertical-align: top;"> <td style="vertical-align:top">
<div> <div>
#if $cur_result['description']: #if $cur_result['description']
<span class="title" style="vertical-align:middle;">Plot:</span> <span class="title" style="vertical-align:middle">Plot:</span>
<img class="ep_summaryTrigger" src="$sbRoot/images/plus.png" height="16" width="16" alt="" title="Toggle Summary" /><div class="ep_summary">$cur_result['description']</div> <img class="ep_summaryTrigger" src="$sbRoot/images/plus.png" height="16" width="16" alt="" title="Toggle Summary" /><div class="ep_summary">$cur_result['description']</div>
#else: #else
<span class="title ep_summaryTriggerNone" style="vertical-align:middle;">Plot:</span> <span class="title ep_summaryTriggerNone" style="vertical-align:middle">Plot:</span>
<img class="ep_summaryTriggerNone" src="$sbRoot/images/plus.png" height="16" width="16" alt="" /> <img class="ep_summaryTriggerNone" src="$sbRoot/images/plus.png" height="16" width="16" alt="" />
#end if #end if
</div> </div>
@ -600,41 +649,52 @@
</tr> </tr>
</table> </table>
</div> </div>
</div> </div>
<!-- end $cur_result['show_name'] //--> <!-- end $cur_result['show_name'] //-->
#end for #end for
</div>
<!-- end non list view //--> <!-- end non list view //-->
#end if #end if
##
#if 'daybyday' == $layout: #if 'daybyday' == $layout
##
#set $shows_overdue = [] #set $shows_overdue = []
#set $shows_soon = [] #set $shows_soon = []
#set $shows_future = [] #set $shows_future = []
#set $onair = []
#set $backart = []
#set $state_overdue = 'listing-overdue' #set $state_overdue = 'listing-overdue'
#set $state_current = 'listing-current' #set $state_current = 'listing-current'
#set $state_soon = 'listing-soon' #set $state_soon = 'listing-soon'
#set $state_future = 'listing-default' #set $state_future = 'listing-default'
#for $cur_result in $sql_results: #for $cur_result in $sql_results
#if int($cur_result['paused']) and not $sickbeard.EPISODE_VIEW_DISPLAY_PAUSED: #if int($cur_result['paused']) and not $sg_var('EPISODE_VIEW_DISPLAY_PAUSED')
#continue #continue
#end if #end if
#if $cur_result['runtime']: #if $cur_result['runtime']
#set $air_date = $cur_result['localtime'].date() #set $air_date = $cur_result['localtime'].date()
#set $end_datetime = $cur_result['localtime'] + datetime.timedelta(minutes = $cur_result['runtime']) #set $end_datetime = $cur_result['localtime'] + datetime.timedelta(minutes = $cur_result['runtime'])
#if $air_date >= $next_week.date(): #if $air_date >= $next_week.date()
#set $cur_result['state'] = '' #set $cur_result['state'] = ''
$shows_future.append($cur_result) $shows_future.append($cur_result)
#elif $cur_result['localtime'] > $today #elif $cur_result['localtime'] > $today
#set $cur_result['state'] = '' #set $cur_result['state'] = ''
$shows_soon.append($cur_result) $shows_soon.append($cur_result)
#set $dif = $cur_result['localtime'] - $today
#set $until_hrs = (divmod($dif.days * 86400 + $dif.seconds, 60)[0]) / 60
#if 24 >= $until_hrs and $cur_result['showid'] not in $backart
$backart.append($cur_result['showid'])
#end if
#elif $end_datetime > $today #elif $end_datetime > $today
#set $cur_result['state'] = $state_current #set $cur_result['state'] = $state_current
#set $cur_result['state-title'] = 'Currently On Air' #set $cur_result['state-title'] = 'Currently On Air'
$shows_soon.append($cur_result) $shows_soon.append($cur_result)
#elif $air_date == $today.date(): #if $cur_result['showid'] not in $onair
$onair.append($cur_result['showid'])
#end if
#elif $air_date == $today.date()
#set $cur_result['state'] = $state_overdue #set $cur_result['state'] = $state_overdue
#set $cur_result['state-title'] = 'Overdue' #set $cur_result['state-title'] = 'Overdue'
$shows_soon.append($cur_result) $shows_soon.append($cur_result)
@ -657,16 +717,42 @@
#set $rounded_week = len($dates_future)/7*7 + int(bool(len($dates_future)%7))*7 #set $rounded_week = len($dates_future)/7*7 + int(bool(len($dates_future)%7))*7
#set $dates_future += [$dates_future[-1] + datetime.timedelta(days = 1 + $i) for $i in range($rounded_week - len($dates_future))] #set $dates_future += [$dates_future[-1] + datetime.timedelta(days = 1 + $i) for $i in range($rounded_week - len($dates_future))]
#set $num_weeks = $rounded_week/7 #set $num_weeks = $rounded_week/7
#slurp
<span style="position:absolute;left:-999px;height:0px">
<img src="$sbRoot/images/poster_thumb.jpg" alt=""><img src="$sbRoot/images/banner_thumb.jpg" alt="">
</span>
#if $varExists('fanart')
<div id="background-container">
#set $backlist = $backart
#if $onair
#import random
$random.shuffle($onair)
#set $backlist = $onair
#end if
<input type="hidden" id="sbRoot" value="$sbRoot" /> #if len($backlist)
<ul>
#set $start_image = True
#for $show_id in $backlist
#for ($image, $rating) in $fanart.get($show_id, [])
<li class="#echo ' '.join((x for x in ({10:'group', 20:'fave', 30:'avoid'}.get($rating, ''), ('', 'background first-load')[$start_image]) if x)) #" style="background-image:url($sbRoot/showPoster/?show=$show_id&which=fanart_$image)"></li>
#set $start_image = False
#end for
#end for
</ul>
#end if
</div>
#end if
<div class="daybydayCarouselContainer"> <div class="daybydayCarouselContainer">
<div id="Carousel" class="carousel slide"> <div id="Carousel" class="carousel slide">
<div class="controlsBlock"> #set $wide = int(0 < len($shows_overdue)) + $num_weeks
<div class="controlsBlock" style="#if $wide#width:#echo 42 + (($wide + 1) * 22) + 15 #px#else#background:transparent#end if#">
#if $wide
<a class="left carousel-control" href="#Carousel" data-slide="prev"><i class="glyphicon glyphicon-chevron-left"></i></a> <a class="left carousel-control" href="#Carousel" data-slide="prev"><i class="glyphicon glyphicon-chevron-left"></i></a>
<a class="right carousel-control" href="#Carousel" data-slide="next"><i class="glyphicon glyphicon-chevron-right"></i></a> <a class="right carousel-control" href="#Carousel" data-slide="next"><i class="glyphicon glyphicon-chevron-right"></i></a>
<div class="carousel-indicators"> <ul class="carousel-indicators">
#set $slide_id = 0 #set $slide_id = 0
#if len($shows_overdue) #if len($shows_overdue)
@ -679,7 +765,8 @@
#for $i in range($slide_id, $slide_id + $num_weeks) #for $i in range($slide_id, $slide_id + $num_weeks)
<li data-target="#Carousel" data-slide-to="${i}" class="$state_future#if $state_init[1] == $state_future and $state_init[0] == $i then ' active' else ''#"></li> <li data-target="#Carousel" data-slide-to="${i}" class="$state_future#if $state_init[1] == $state_future and $state_init[0] == $i then ' active' else ''#"></li>
#end for #end for
</div> </ul>
#end if
</div> </div>
<div class="carousel-inner"> <div class="carousel-inner">
@ -704,17 +791,16 @@
<div class="item#if $state_init[1] == $state then ' active' else ''#"> <!-- start $state --> <div class="item#if $state_init[1] == $state then ' active' else ''#"> <!-- start $state -->
<div class="daybydayWrapper"> <div class="daybydayWrapper">
#set $tbl_day = 0 #set $tbl_day = 0
#for $day in $dates #for $day in $dates
##
#set $tbl_day += 1 #set $tbl_day += 1
##
#set $col_class = '' #set $col_class = ''
#if 1 == $tbl_day and $state_soon == $state #if 1 == $tbl_day and $state_soon == $state
#set $col_class = 'today' #set $col_class = 'today '
#end if #end if
#set $col_class = '%s %s' % ($col_class, ('even', 'odd')[1 == tbl_day % 2]) #set $col_class = '%s%s' % ($col_class, ('even', 'odd')[1 == tbl_day % 2])
<div class="day-of-week $col_class"> <div class="day-of-week $col_class">
<div class="day-number"> <div class="day-number">
@ -732,8 +818,8 @@
<div id="$sbdatetime.sbdatetime.sbfdate($day, 'day%j')"> <div id="$sbdatetime.sbdatetime.sbfdate($day, 'day%j')">
#set $day_has_show = False #set $day_has_show = False
#for $cur_result in $shows: #for $cur_result in $shows
#if $day == $cur_result['localtime'].date(): #if $day == $cur_result['localtime'].date()
#set $day_has_show = True #set $day_has_show = True
#set $airtime = $sbdatetime.sbdatetime.sbftime($cur_result['localtime'], markup=True).decode($sickbeard.SYS_ENCODING) #set $airtime = $sbdatetime.sbdatetime.sbftime($cur_result['localtime'], markup=True).decode($sickbeard.SYS_ENCODING)
#set $img_id = '' #set $img_id = ''
@ -746,7 +832,7 @@
<div id="show-${show_id}" class="daybyday-show" data-name="$cur_result['data_show_name']" data-season="$cur_result['season']" data-episode="$cur_result['episode']" data-network="$cur_result['data_network']" data-time="$cur_result['localtime'].strftime('%Y%m%d%H%M')" data-rawname="$cur_result['show_name']"> <div id="show-${show_id}" class="daybyday-show" data-name="$cur_result['data_show_name']" data-season="$cur_result['season']" data-episode="$cur_result['episode']" data-network="$cur_result['data_network']" data-time="$cur_result['localtime'].strftime('%Y%m%d%H%M')" data-rawname="$cur_result['show_name']">
<div class="poster"> <div class="poster">
<a${title_text} href="$sbRoot/home/displayShow?show=${cur_result['showid']}"> <a${title_text} href="$sbRoot/home/displayShow?show=${cur_result['showid']}">
<img${img_id} class="img-responsive${plot_class}" alt="" src="$sbRoot/showPoster/?show=${cur_result['showid']}&amp;which=poster_thumb" /></a> <img${img_id} class="img-responsive${plot_class}" alt="" src="$sbRoot/showPoster/?show=${cur_result['showid']}&amp;which=#echo ('banner', 'poster')[$bool($sg_var('EPISODE_VIEW_POSTERS', True))]#_thumb" /></a>
</div> </div>
<div class="state#if len($cur_result['state']) then ' %s" title="%s"' % ($cur_result['state'], $cur_result['state-title']) else '"' #></div> <div class="state#if len($cur_result['state']) then ' %s" title="%s"' % ($cur_result['state'], $cur_result['state-title']) else '"' #></div>
<div class="text"> <div class="text">
@ -759,7 +845,7 @@
<span class="name">$cur_result['name']</span> <span class="name">$cur_result['name']</span>
</div> </div>
</div> </div>
#if int($cur_result['paused']): #if int($cur_result['paused'])
<span class="over-layer0">[paused]</span> <span class="over-layer0">[paused]</span>
<span class="over-layer1">[paused]</span> <span class="over-layer1">[paused]</span>
#elif $state_current == $cur_result['state'] #elif $state_current == $cur_result['state']
@ -771,7 +857,7 @@
#end if #end if
#end for #end for
#if not $day_has_show: #if not $day_has_show
<div class="daybyday-show"> <div class="daybyday-show">
#set $theday = ('this ', 'to')[1 == $tbl_day and $state_soon == $state] #set $theday = ('this ', 'to')[1 == $tbl_day and $state_soon == $state]
<span class="episode-blank">No shows ${theday}day</span> <span class="episode-blank">No shows ${theday}day</span>
@ -794,24 +880,23 @@
<div class="clearfix"></div> <div class="clearfix"></div>
<script type="text/javascript" charset="utf-8"> #raw
<script>
<!-- <!--
window.setInterval('location.reload(true)', 30*60000); // Refresh every xx minutes window.setInterval('location.reload(true)', 30*60000); // Refresh every xx minutes
\$('#Carousel').carousel({ $('#Carousel').carousel({interval: 0});
interval: 0
});
\$(document).bind('keyup', function(e) { $(document).bind('keyup', function(e) {
if(e.which == 39){ return ((!(e.hasOwnProperty('ctrlKey') && e.ctrlKey) && !(e.hasOwnProperty('altKey') && e.altKey)) && (
\$('.carousel').carousel('next'); (39 == e.which && $('.carousel').carousel('next')) ||
} (37 == e.which && $('.carousel').carousel('prev'))) || !0);
else if(e.which == 37){
\$('.carousel').carousel('prev');
}
}); });
//--> //-->
</script> </script>
#end raw
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_bottom.tmpl') #if $varExists('fanart') and $layout in 'daybyday'
#include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_livepanel.tmpl')
#end if
#include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_bottom.tmpl')

View file

@ -6,15 +6,17 @@
#from sickbeard import history #from sickbeard import history
#from sickbeard import providers #from sickbeard import providers
#from sickbeard.providers import generic #from sickbeard.providers import generic
<% def sg_var(varname, default=False): return getattr(sickbeard, varname, default) %>#slurp#
<% def sg_str(varname, default=''): return getattr(sickbeard, varname, default) %>#slurp#
## ##
#set global $title = 'History' #set global $title = 'History'
#set global $header = 'History' #set global $header = 'History'
#set global $sbPath = '..' #set global $sbPath = '..'
#set global $topmenu = 'history' #set global $topmenu = 'history'
#set $layout = $sickbeard.HISTORY_LAYOUT #set $layout = $sg_str('HISTORY_LAYOUT', 'detailed')
## ##
#import os.path #import os.path
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_top.tmpl') #include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_top.tmpl')
<script type="text/javascript"> <script type="text/javascript">
<!-- <!--
@ -61,13 +63,13 @@
}); });
#set $fuzzydate = 'airdate' #set $fuzzydate = 'airdate'
#if $sickbeard.FUZZY_DATING #if $sg_var('FUZZY_DATING')
fuzzyMoment({ fuzzyMoment({
containerClass: '.${fuzzydate}', containerClass: '.${fuzzydate}',
dateHasTime: !0, dateHasTime: !0,
dateFormat: '${sickbeard.DATE_PRESET}', dateFormat: '$sg_str('DATE_PRESET', '%x')',
timeFormat: '${sickbeard.TIME_PRESET_W_SECONDS}', timeFormat: '$sg_str('TIME_PRESET_W_SECONDS', '%I:%M:%S %p')',
trimZero: #echo ('!1', '!0')[$sickbeard.TRIM_ZERO]#, trimZero: #echo ('!1', '!0')[$sg_var('TRIM_ZERO')]#,
dtGlue: ', ' dtGlue: ', '
}); });
#end if #end if
@ -93,8 +95,8 @@
<span style="margin-left:5px">Layout: <span style="margin-left:5px">Layout:
<select name="HistoryLayout" class="form-control form-control-inline input-sm" onchange="location = this.options[this.selectedIndex].value"> <select name="HistoryLayout" class="form-control form-control-inline input-sm" onchange="location = this.options[this.selectedIndex].value">
<option value="$sbRoot/setHistoryLayout/?layout=compact"#echo ('', $html_selected)['compact' == $sickbeard.HISTORY_LAYOUT]#>Compact</option> <option value="$sbRoot/setHistoryLayout/?layout=compact"#echo ('', $html_selected)['compact' == $sg_str('HISTORY_LAYOUT')]#>Compact</option>
<option value="$sbRoot/setHistoryLayout/?layout=detailed"#echo ('', $html_selected)['detailed' == $sickbeard.HISTORY_LAYOUT]#>Detailed</option> <option value="$sbRoot/setHistoryLayout/?layout=detailed"#echo ('', $html_selected)['detailed' == $sg_str('HISTORY_LAYOUT', 'detailed')]#>Detailed</option>
</select> </select>
</span> </span>
</div> </div>
@ -121,10 +123,10 @@
<tbody> <tbody>
#for $hItem in $historyResults #for $hItem in $historyResults
#set $curStatus, $curQuality = $Quality.splitCompositeStatus(int($hItem['action'])) #set $curStatus, $curQuality = $Quality.splitCompositeStatus(int($hItem['action']))
#set $data_name = (re.sub('^((?:A(?!\s+to)n?)|The)\s(\w)', r'\2', $hItem['show_name']), $hItem['show_name'])[$sickbeard.SORT_ARTICLE] #set $data_name = (re.sub('^((?:A(?!\s+to)n?)|The)\s(\w)', r'\2', $hItem['show_name']), $hItem['show_name'])[$sg_var('SORT_ARTICLE')]
#set $display_name = '<span data-name="%s">%s - S%02iE%02i</span>' % ( #set $display_name = '<span data-name="%s">%s - S%02iE%02i</span>' % (
$data_name, $data_name,
(re.sub('^((?:A(?!\s+to)n?)|The)\s(\w)', r'<span class="article">\1</span> \2', $hItem['show_name']), $hItem['show_name'])[$sickbeard.SORT_ARTICLE], (re.sub('^((?:A(?!\s+to)n?)|The)\s(\w)', r'<span class="article">\1</span> \2', $hItem['show_name']), $hItem['show_name'])[$sg_var('SORT_ARTICLE')],
int(hItem['season']), int(hItem['episode'])) int(hItem['season']), int(hItem['episode']))
<tr> <tr>
#set $curdatetime = $datetime.datetime.strptime(str($hItem['date']), $history.dateFormat) #set $curdatetime = $datetime.datetime.strptime(str($hItem['date']), $history.dateFormat)
@ -156,7 +158,7 @@
#end if #end if
#end if #end if
</td> </td>
<td><span class="hide">$curQuality</span><span class="quality $Quality.qualityStrings[$curQuality].replace('720p', 'HD720p').replace('1080p', 'HD1080p').replace('RawHD TV', 'RawHD').replace('HD TV', 'HD720p')">$Quality.qualityStrings[$curQuality]</span></td> <td><span class="hide">$curQuality</span><span class="quality $Quality.get_quality_css($curQuality)">$Quality.qualityStrings[$curQuality]</span></td>
</tr> </tr>
#end for #end for
@ -164,10 +166,10 @@
<thead> <thead>
<tr> <tr>
<th class="nowrap">Time</th> <th class="nowrap">Time</th>
<th width="#echo '3%s%%' % ('5', '0')[sickbeard.USE_SUBTITLES]#">Episode</th> <th width="#echo '3%s%%' % ('5', '0')[$sg_var('USE_SUBTITLES')]#">Episode</th>
<th>Snatched</th> <th>Snatched</th>
<th>Downloaded</th> <th>Downloaded</th>
#if sickbeard.USE_SUBTITLES #if $sg_var('USE_SUBTITLES')
<th>Subtitled</th> <th>Subtitled</th>
#end if #end if
<th width="14%">Quality</th> <th width="14%">Quality</th>
@ -183,10 +185,10 @@
<tbody> <tbody>
#for $hItem in $compactResults #for $hItem in $compactResults
#set $curdatetime = $datetime.datetime.strptime(str($hItem['actions'][0]['time']), $history.dateFormat) #set $curdatetime = $datetime.datetime.strptime(str($hItem['actions'][0]['time']), $history.dateFormat)
#set $data_name = (re.sub('^((?:A(?!\s+to)n?)|The)\s(\w)', r'\2', $hItem['show_name']), $hItem['show_name'])[$sickbeard.SORT_ARTICLE] #set $data_name = (re.sub('^((?:A(?!\s+to)n?)|The)\s(\w)', r'\2', $hItem['show_name']), $hItem['show_name'])[$sg_var('SORT_ARTICLE')]
#set $display_name = '<span data-name="%s">%s - S%02iE%02i</span>' % ( #set $display_name = '<span data-name="%s">%s - S%02iE%02i</span>' % (
$data_name, $data_name,
(re.sub('^((?:A(?!\s+to)n?)|The)\s(\w)', r'<span class="article">\1</span> \2', $hItem['show_name']), $hItem['show_name'])[$sickbeard.SORT_ARTICLE], (re.sub('^((?:A(?!\s+to)n?)|The)\s(\w)', r'<span class="article">\1</span> \2', $hItem['show_name']), $hItem['show_name'])[$sg_var('SORT_ARTICLE')],
int(hItem['season']), int(hItem['episode'])) int(hItem['season']), int(hItem['episode']))
#set $prov_list = [] #set $prov_list = []
#set $down_list = [] #set $down_list = []
@ -245,7 +247,7 @@
<td> <td>
#echo ' '.join($down_list)# #echo ' '.join($down_list)#
</td> </td>
#if sickbeard.USE_SUBTITLES #if $sg_var('USE_SUBTITLES')
<td> <td>
#for $action in reversed($hItem['actions']) #for $action in reversed($hItem['actions'])
#set $curStatus, $curQuality = $Quality.splitCompositeStatus(int($action['action'])) #set $curStatus, $curQuality = $Quality.splitCompositeStatus(int($action['action']))
@ -258,7 +260,7 @@
#end for #end for
</td> </td>
#end if #end if
<td quality="$curQuality"><span class="quality $Quality.qualityStrings[$curQuality].replace('720p', 'HD720p').replace('1080p', 'HD1080p').replace('RawHD TV', 'RawHD').replace('HD TV', 'HD720p')">$Quality.qualityStrings[$curQuality]</span></td> <td quality="$curQuality"><span class="quality $Quality.get_quality_css($curQuality)">$Quality.qualityStrings[$curQuality]</span></td>
</tr> </tr>
#end for #end for
@ -266,4 +268,4 @@
</tbody> </tbody>
</table> </table>
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_bottom.tmpl') #include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_bottom.tmpl')

View file

@ -2,6 +2,8 @@
#import datetime #import datetime
#from sickbeard.common import * #from sickbeard.common import *
#from sickbeard import sbdatetime, network_timezones #from sickbeard import sbdatetime, network_timezones
<% def sg_var(varname, default=False): return getattr(sickbeard, varname, default) %>#slurp#
<% def sg_str(varname, default=''): return getattr(sickbeard, varname, default) %>#slurp#
## ##
#set global $title = 'Home' #set global $title = 'Home'
#set global $header = 'Show List' #set global $header = 'Show List'
@ -11,18 +13,18 @@
#set fuzzydate = 'airdate' #set fuzzydate = 'airdate'
## ##
#import os.path #import os.path
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_top.tmpl') #include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_top.tmpl')
<script> <script>
var config = { var config = {
isPoster: #echo ['!1','!0']['poster' == $sickbeard.HOME_LAYOUT]#, isPoster: #echo ['!1','!0']['poster' == $sg_var('HOME_LAYOUT')]#,
sortArticle: #echo ['!1','!0'][$sickbeard.SORT_ARTICLE]#, sortArticle: #echo ['!1','!0'][$sg_var('SORT_ARTICLE')]#,
homeSearchFocus: #echo ['!1','!0'][$sickbeard.HOME_SEARCH_FOCUS]#, homeSearchFocus: #echo ['!1','!0'][$sg_var('HOME_SEARCH_FOCUS', True)]#,
fuzzyDating: #echo ['!1','!0'][$sickbeard.FUZZY_DATING]#, fuzzyDating: #echo ['!1','!0'][$sg_var('FUZZY_DATING')]#,
timeZero: #echo ['!1','!0'][$sickbeard.TRIM_ZERO]#, timeZero: #echo ['!1','!0'][$sg_var('TRIM_ZERO')]#,
datePreset: "$sickbeard.DATE_PRESET", datePreset: "$sg_str('DATE_PRESET', '%x')",
timePreset: "$sickbeard.TIME_PRESET", timePreset: "$sg_str('TIME_PRESET', '%I:%M %p')",
posterSortby: "$sickbeard.POSTER_SORTBY", posterSortby: "$sg_var('POSTER_SORTBY')",
posterSortdir: #echo ['!1','!0'][$sickbeard.POSTER_SORTDIR]#, posterSortdir: #echo ['!1','!0'][$sg_var('POSTER_SORTDIR', True)]#,
fuzzydate: ".$fuzzydate", fuzzydate: ".$fuzzydate",
}; };
</script> </script>
@ -33,33 +35,33 @@
#set $tab = 1 #set $tab = 1
#set $selected = ' selected="selected"' #set $selected = ' selected="selected"'
#if 'poster' == $layout #if 'poster' == $layout
<div> <div id="top-row">
<span>Sort By: <span>Sort By:
<select id="postersort" class="form-control form-control-inline input-sm" tabindex="$tab#set $tab += 1#"> <select id="postersort" class="form-control form-control-inline input-sm" tabindex="$tab#set $tab += 1#">
<option value="name" data-sort="$sbRoot/setPosterSortBy/?sort=name"#echo $selected if 'name' == sickbeard.POSTER_SORTBY else ''#>Name</option> <option value="name" data-sort="$sbRoot/setPosterSortBy/?sort=name"#echo $selected if 'name' == $sg_str('POSTER_SORTBY', 'name') else ''#>Name</option>
<option value="date" data-sort="$sbRoot/setPosterSortBy/?sort=date"#echo $selected if 'date' == sickbeard.POSTER_SORTBY else ''#>Next Episode</option> <option value="date" data-sort="$sbRoot/setPosterSortBy/?sort=date"#echo $selected if 'date' == $sg_str('POSTER_SORTBY') else ''#>Next Episode</option>
<option value="network" data-sort="$sbRoot/setPosterSortBy/?sort=network"#echo $selected if 'network' == sickbeard.POSTER_SORTBY else ''#>Network</option> <option value="network" data-sort="$sbRoot/setPosterSortBy/?sort=network"#echo $selected if 'network' == $sg_str('POSTER_SORTBY') else ''#>Network</option>
<option value="progress" data-sort="$sbRoot/setPosterSortBy/?sort=progress"#echo $selected if 'progress' == sickbeard.POSTER_SORTBY else ''#>Progress</option> <option value="progress" data-sort="$sbRoot/setPosterSortBy/?sort=progress"#echo $selected if 'progress' == $sg_str('POSTER_SORTBY') else ''#>Progress</option>
<option value="quality" data-sort="$sbRoot/setPosterSortBy/?sort=quality"#echo $selected if 'quality' == sickbeard.POSTER_SORTBY else ''#>Quality</option> <option value="quality" data-sort="$sbRoot/setPosterSortBy/?sort=quality"#echo $selected if 'quality' == $sg_str('POSTER_SORTBY') else ''#>Quality</option>
</select> </select>
</span> </span>
<span style="margin-left:5px">Sort Order: <span style="margin-left:5px">Sort Order:
<select id="postersortdirection" class="form-control form-control-inline input-sm" tabindex="$tab#set $tab += 1#"> <select id="postersortdirection" class="form-control form-control-inline input-sm" tabindex="$tab#set $tab += 1#">
<option value="true" data-sort="$sbRoot/setPosterSortDir/?direction=1"#echo $selected if 1 == sickbeard.POSTER_SORTDIR else ''#>Asc</option> <option value="true" data-sort="$sbRoot/setPosterSortDir/?direction=1"#echo $selected if 1 == $sg_var('POSTER_SORTDIR', 1) else ''#>Asc</option>
<option value="false" data-sort="$sbRoot/setPosterSortDir/?direction=0"#echo $selected if 0 == sickbeard.POSTER_SORTDIR else ''#>Desc</option> <option value="false" data-sort="$sbRoot/setPosterSortDir/?direction=0"#echo $selected if 0 == $sg_var('POSTER_SORTDIR') else ''#>Desc</option>
</select> </select>
</span> </span>
<span style="margin-left:5px">Layout: <span style="margin-left:5px" class="no-marginr">Layout:
#else #else
<span class="pull-right">Layout: <span id="top-row" class="pull-right no-marginr">Layout:
#end if #end if
<select style="margin-bottom:10px" name="layout" class="form-control form-control-inline input-sm" onchange="location = this.options[this.selectedIndex].value;" tabindex="$tab#set $tab += 1#"> <select style="margin-bottom:10px" name="layout" class="form-control form-control-inline input-sm" onchange="location = this.options[this.selectedIndex].value;" tabindex="$tab#set $tab += 1#">
<option value="$sbRoot/setHomeLayout/?layout=poster"#echo $selected if 'poster' == sickbeard.HOME_LAYOUT else ''#>Poster</option> <option value="$sbRoot/setHomeLayout/?layout=poster"#echo $selected if 'poster' == $sg_str('HOME_LAYOUT', 'poster') else ''#>Poster</option>
<option value="$sbRoot/setHomeLayout/?layout=small"#echo $selected if 'small' == sickbeard.HOME_LAYOUT else ''#>Small Poster</option> <option value="$sbRoot/setHomeLayout/?layout=small"#echo $selected if 'small' == $sg_str('HOME_LAYOUT') else ''#>Small Poster</option>
<option value="$sbRoot/setHomeLayout/?layout=banner"#echo $selected if 'banner' == sickbeard.HOME_LAYOUT else ''#>Banner</option> <option value="$sbRoot/setHomeLayout/?layout=banner"#echo $selected if 'banner' == $sg_str('HOME_LAYOUT') else ''#>Banner</option>
<option value="$sbRoot/setHomeLayout/?layout=simple"#echo $selected if 'simple' == sickbeard.HOME_LAYOUT else ''#>Simple</option> <option value="$sbRoot/setHomeLayout/?layout=simple"#echo $selected if 'simple' == $sg_str('HOME_LAYOUT') else ''#>Simple</option>
</select> </select>
</span> </span>
@ -89,7 +91,7 @@
## ##
#for $curLoadingShow in $sickbeard.showQueueScheduler.action.loadingShowList #for $curLoadingShow in $sickbeard.showQueueScheduler.action.loadingShowList
## ##
#if $curLoadingShow.show != None and $curLoadingShow.show in $sickbeard.showList #if $curLoadingShow.show != None and $curLoadingShow.show in $sg_str('showList')
#continue #continue
#end if #end if
## ##
@ -116,7 +118,7 @@
#set $cur_total = 0 #set $cur_total = 0
#set $download_stat_tip = '' #set $download_stat_tip = ''
#set $display_status = $curShow.status #set $display_status = $curShow.status
#set $display_name = (re.sub('^((?:A(?!\s+to)n?)|The)\s(\w)', r'<span class="article">\1</span> \2', $curShow.name), $curShow.name)[$sickbeard.SORT_ARTICLE] #set $display_name = (re.sub('^((?:A(?!\s+to)n?)|The)\s(\w)', r'<span class="article">\1</span> \2', $curShow.name), $curShow.name)[$sg_var('SORT_ARTICLE')]
#if None is not $display_status #if None is not $display_status
#if re.search(r'(?i)(?:new|returning)\s*series', $curShow.status) #if re.search(r'(?i)(?:new|returning)\s*series', $curShow.status)
#set $display_status = 'Continuing' #set $display_status = 'Continuing'
@ -272,7 +274,7 @@
<tbody> <tbody>
#for $curLoadingShow in $sickbeard.showQueueScheduler.action.loadingShowList #for $curLoadingShow in $sickbeard.showQueueScheduler.action.loadingShowList
#if $curLoadingShow.show != None and $curLoadingShow.show in $sickbeard.showList #if $curLoadingShow.show != None and $curLoadingShow.show in $sg_str('showList')
#continue #continue
#end if #end if
## ##
@ -302,7 +304,7 @@
#set $cur_downloaded = 0 #set $cur_downloaded = 0
#set $cur_total = 0 #set $cur_total = 0
#set $download_stat_tip = '' #set $download_stat_tip = ''
#set $display_name = (re.sub('^((?:A(?!\s+to)n?)|The)\s(\w)', r'<span class="article">\1</span> \2', $curShow.name), $curShow.name)[$sickbeard.SORT_ARTICLE] #set $display_name = (re.sub('^((?:A(?!\s+to)n?)|The)\s(\w)', r'<span class="article">\1</span> \2', $curShow.name), $curShow.name)[$sg_var('SORT_ARTICLE')]
## ##
#if $curShow.indexerid in $show_stat #if $curShow.indexerid in $show_stat
#set $cur_airs_next = $show_stat[$curShow.indexerid]['ep_airs_next'] #set $cur_airs_next = $show_stat[$curShow.indexerid]['ep_airs_next']
@ -437,4 +439,4 @@
## ##
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_bottom.tmpl') #include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_bottom.tmpl')

View file

@ -1,22 +1,24 @@
#import sickbeard #import sickbeard
#from sickbeard.common import * #from sickbeard.common import *
<% def sg_var(varname, default=False): return getattr(sickbeard, varname, default) %>#slurp#
<% def sg_str(varname, default=''): return getattr(sickbeard, varname, default) %>#slurp#
## ##
#set global $title = 'Existing Show' #set global $title = 'Import'
#set global $header = 'Existing Show' #set global $header = $title
#set global $sbPath = '../..' #set global $sbPath = '../..'
#set global $statpath = '../..' #set global $statpath = '../..'
#set global $topmenu = 'home' #set global $topmenu = 'home'
## ##
#import os.path #import os.path
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_top.tmpl') #include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_top.tmpl')
<script type="text/javascript" charset="utf-8"> <script type="text/javascript" charset="utf-8">
<!-- <!--
var config = { sortArticle: #echo ['!1','!0'][$sickbeard.SORT_ARTICLE]# } var config = { sortArticle: #echo ['!1','!0'][$sg_var('SORT_ARTICLE')]# }
\$.sgSid = '$kwargs.get('sid', '')'; \$.sgSid = '$kwargs.get('sid', '')';
\$.sgHashDir = '$kwargs.get('hash_dir', '')'; \$.sgHashDir = '$kwargs.get('hash_dir', '')';
\$(document).ready(function(){ \$(document).ready(function(){
\$('#tabs').tabs({ collapsible: !0, selected: #echo ('0','-1')[any($sickbeard.ROOT_DIRS)]# }); \$('#tabs').tabs({ collapsible: !0, selected: #echo ('0', '-1')[any($sg_str('ROOT_DIRS'))]# });
}); });
//--> //-->
</script> </script>
@ -31,8 +33,9 @@ var config = { sortArticle: #echo ['!1','!0'][$sickbeard.SORT_ARTICLE]# }
<h1 class="title">$title</h1> <h1 class="title">$title</h1>
#end if #end if
<image class="preload-image" style="position:absolute;top:-999px" src="$sbRoot/images/loading32<%= '-dark' if 'dark' == sickbeard.THEME_NAME else '' %>.gif" width="32" height="32" border="0"> <image class="preload-image" style="position:absolute;top:-999px" src="$sbRoot/images/loading32#echo ('', '-dark')['dark' == $sg_str('THEME_NAME', 'dark')]#.gif" width="32" height="32" border="0">
<h3>Existing show folders</h3>
<form id="addShowForm" method="post" action="$sbRoot/home/addShows/addNewShow" accept-charset="utf-8"> <form id="addShowForm" method="post" action="$sbRoot/home/addShows/addNewShow" accept-charset="utf-8">
<span#if $kwargs.get('hash_dir', None)# class="hide"#end if#> <span#if $kwargs.get('hash_dir', None)# class="hide"#end if#>
@ -50,12 +53,12 @@ var config = { sortArticle: #echo ['!1','!0'][$sickbeard.SORT_ARTICLE]# }
</ul> </ul>
<div id="tabs-1" class="existingtabs"> <div id="tabs-1" class="existingtabs">
<div style="width: 430px; margin: 0px auto"> <div style="width: 430px; margin: 0px auto">
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_rootDirs.tmpl') #include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_rootDirs.tmpl')
</div> </div>
</div> </div>
<div id="tabs-2"> <div id="tabs-2">
<div class="stepDiv"> <div class="stepDiv" style="padding-top:25px">
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_addShowOptions.tmpl') #include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_addShowOptions.tmpl')
</div> </div>
</div> </div>
</div> </div>
@ -87,4 +90,4 @@ var config = { sortArticle: #echo ['!1','!0'][$sickbeard.SORT_ARTICLE]# }
</form> </form>
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_bottom.tmpl') #include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_bottom.tmpl')

View file

@ -18,36 +18,36 @@
<div id="addShowPortal"> <div id="addShowPortal">
<a class="btn btn-large" href="$sbRoot/home/addShows/new_show/"> <a class="btn btn-large" href="$sbRoot/home/addShows/new_show/">
<div class="button"><div class="icon-addnewshow square-32"></div></div> <div class="button"><span style="font-size:32px"><i class="sgicon-addshow"></i></span></div>
<div class="buttontext"> <div class="buttontext">
<h3>Add new show</h3> <h3>Search</h3>
<p>Search a TV database for a show.</p> <p>find show at TV info source</p>
</div> </div>
</a> </a>
<a class="btn btn-large" href="$sbRoot/home/addShows/trakt_default/"> <a class="btn btn-large" href="$sbRoot/home/addShows/trakt_default/">
<div class="button"><div class="icon-addrecommendedshow square-32"></div></div> <div class="button"><span style="font-size:32px"><i class="sgicon-trakt"></i></span></div>
<div class="buttontext"> <div class="buttontext">
<h3>Add from Trakt</h3> <h3>Trakt cards</h3>
<p>Browse trends, recommended and more.</p> <p>trends, tailored suggestions...</p>
</div> </div>
</a> </a>
<div style="clear:both;font-size:2px">&nbsp;</div> <div style="clear:both;font-size:2px">&nbsp;</div>
<a class="btn btn-large" href="$sbRoot/home/addShows/existing_shows/"> <a class="btn btn-large" href="$sbRoot/home/addShows/import_shows/">
<div class="button"><div class="icon-addexistingshow square-32"></div></div> <div class="button"><div class="icon-addexistingshow square-32"></div></div>
<div class="buttontext"> <div class="buttontext">
<h3>Add existing shows</h3> <h3>Import</h3>
<p>Scan parent folders to import into SickGear.</p> <p>existing shows</p>
</div> </div>
</a> </a>
<a class="btn btn-large" href="$sbRoot/home/addShows/imdb_default/"> <a class="btn btn-large" href="$sbRoot/home/addShows/imdb_default/">
<div class="button"><div class="img-imdb square-32"></div></div> <div class="button"><span style="font-size:32px"><i class="sgicon-imdb"></i></span></div>
<div class="buttontext"> <div class="buttontext">
<h3>Add from IMDb</h3> <h3>IMDb cards</h3>
<p>Browse popular for a show to add.</p> <p>popular decades, watchlists...</p>
</div> </div>
</a> </a>
@ -57,16 +57,16 @@
<a class="btn btn-large" href="$sbRoot/home/addShows/anime_default/"> <a class="btn btn-large" href="$sbRoot/home/addShows/anime_default/">
<div class="button"><div class="img-anime square-32"></div></div> <div class="button"><div class="img-anime square-32"></div></div>
<div class="buttontext"> <div class="buttontext">
<h3>Add anime show</h3> <h3>Anime cards</h3>
<p>Browse anime to add.</p> <p>browse anime to add</p>
</div> </div>
</a> </a>
#else #else
<div class="buttontext" style="margin:0px 7px 14px;padding:0 5px 0 28px"> <div class="buttontext" style="margin:0px 7px 14px;padding:0 5px 0 25px">
<div class="button"><div class="img-anime square-32"></div></div> <div class="button"><div class="img-anime square-32"></div></div>
<div class="buttontext"> <div class="buttontext">
<h3>Add anime show</h3> <h3>Anime cards</h3>
<p>To use, enable AniDB in <a href="$sbRoot/config/anime/">Config/Anime</a>.</p> <p>to use, enable AniDB <a href="$sbRoot/config/anime/">here</a></p>
</div> </div>
</div> </div>
#end if #end if

View file

@ -5,6 +5,8 @@
#from sickbeard.common import * #from sickbeard.common import *
#from sickbeard import sbdatetime #from sickbeard import sbdatetime
#from sickbeard.helpers import anon_url #from sickbeard.helpers import anon_url
<% def sg_var(varname, default=False): return getattr(sickbeard, varname, default) %>#slurp#
<% def sg_str(varname, default=''): return getattr(sickbeard, varname, default) %>#slurp#
## ##
#set global $title='Browse %s Shows' % $browse_type #set global $title='Browse %s Shows' % $browse_type
#set global $header='Browse Shows' #set global $header='Browse Shows'
@ -13,7 +15,7 @@
#set global $page_body_attr = 'browse-list' #set global $page_body_attr = 'browse-list'
## ##
#import os.path #import os.path
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_top.tmpl') #include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_top.tmpl')
<script type="text/javascript" src="$sbRoot/js/plotTooltip.js?v=$sbPID"></script> <script type="text/javascript" src="$sbRoot/js/plotTooltip.js?v=$sbPID"></script>
@ -51,7 +53,7 @@
premiered: '[data-premiered] parseInt', premiered: '[data-premiered] parseInt',
name: function( itemElem ) { name: function( itemElem ) {
var name = \$( itemElem ).attr('data-name') || ''; var name = \$( itemElem ).attr('data-name') || '';
#if not $sickbeard.SORT_ARTICLE: #if not $sg_var('SORT_ARTICLE'):
name = name.replace(/^(?:(?:A(?!\s+to)n?)|The)\s(\w)/i, '$1'); name = name.replace(/^(?:(?:A(?!\s+to)n?)|The)\s(\w)/i, '$1');
#end if #end if
return name.toLowerCase(); return name.toLowerCase();
@ -128,21 +130,6 @@
<option value="*" selected="selected">All<%= ' (%d)' % count_all_shows %></option> <option value="*" selected="selected">All<%= ' (%d)' % count_all_shows %></option>
<option value=".notinlibrary">Not In Library<%= ' (%d)' % (count_all_shows - count_inlibrary) %></option> <option value=".notinlibrary">Not In Library<%= ' (%d)' % (count_all_shows - count_inlibrary) %></option>
<option value=".inlibrary">In Library<%= ' (%d)' % count_inlibrary %></option> <option value=".inlibrary">In Library<%= ' (%d)' % count_inlibrary %></option>
#if $browse_type in ('IMDb', 'Trakt', 'AniDB')
<optgroup label="Other Services">
#if 'IMDb' == $browse_type
<option value="trakt_default">Trakt</option>
#elif 'Trakt' == $browse_type
<option value="imdb_default">IMDb</option>
#elif 'AniDB' == $browse_type
<option value="imdb_default">IMDb</option>
<option value="trakt_default">Trakt</option>
#end if
#if $sickbeard.USE_ANIDB and $browse_type in ('IMDb', 'Trakt')
<option value="anime_default">AniDB</option>
#end if
</optgroup>
#end if
#set $selected = ' class="selected"' #set $selected = ' class="selected"'
#if 'Trakt' == $browse_type #if 'Trakt' == $browse_type
<optgroup label="Trakt"> <optgroup label="Trakt">
@ -162,11 +149,11 @@
<option value="trakt_played?period=year"#echo ('', selected)['played-year' == $mode]#>Most Played</option> <option value="trakt_played?period=year"#echo ('', selected)['played-year' == $mode]#>Most Played</option>
<option value="trakt_collected?period=year"#echo ('', selected)['collected-year' == $mode]#>Most Collected</option> <option value="trakt_collected?period=year"#echo ('', selected)['collected-year' == $mode]#>Most Collected</option>
</optgroup> </optgroup>
#if any($sickbeard.TRAKT_ACCOUNTS) #if any($sg_var('TRAKT_ACCOUNTS', []))
<optgroup label="Trakt recommended"> <optgroup label="Trakt recommended">
#for $account in $sickbeard.TRAKT_ACCOUNTS #for $account in $sg_var('TRAKT_ACCOUNTS')
#if $sickbeard.TRAKT_ACCOUNTS[$account].active and $sickbeard.TRAKT_ACCOUNTS[$account].name #if $sg_var('TRAKT_ACCOUNTS').get($account).active and $sg_var('TRAKT_ACCOUNTS').get($account).name
<option value="trakt_recommended?account=$account"#echo ('', selected)[('recommended-%s' % $account) == $mode]#>for $sickbeard.TRAKT_ACCOUNTS[$account].name</option> <option value="trakt_recommended?account=$account"#echo ('', selected)[('recommended-%s' % $account) == $mode]#>for $sg_var('TRAKT_ACCOUNTS').get($account).name</option>
#end if #end if
#end for #end for
#else #else
@ -186,8 +173,8 @@
#end if #end if
#if not hasattr($sickbeard, 'IMDB_ACCOUNTS')#<optgroup label="Restart SickGear to reveal"><option>new options after restart</option></optgroup>#else# #if not hasattr($sickbeard, 'IMDB_ACCOUNTS')#<optgroup label="Restart SickGear to reveal"><option>new options after restart</option></optgroup>#else#
<optgroup label="IMDb Watchlists"> <optgroup label="IMDb Watchlists">
#if any($sickbeard.IMDB_ACCOUNTS) #if any($sg_var('IMDB_ACCOUNTS', []))
#for $i, $v in $enumerate($sickbeard.IMDB_ACCOUNTS) #for $i, $v in $enumerate($sg_var('IMDB_ACCOUNTS'))
#if not $i % 2 #if not $i % 2
#set $id = $v #set $id = $v
#elif not $v.startswith('(Off) ') #elif not $v.startswith('(Off) ')
@ -256,11 +243,11 @@
</div> </div>
<div class="show-title"> <div class="show-title">
<%= ((re.sub('^((?:A(?!\s+to)n?)|The)\s(\w)', r'<span class="article">\1</span> \2', this_show['title']), this_show['title'])[sickbeard.SORT_ARTICLE], '<span>&nbsp;</span>')['' == this_show['title']] %> #echo ((re.sub('^((?:A(?!\s+to)n?)|The)\s(\w)', r'<span class="article">\1</span> \2', $this_show['title']), $this_show['title'])[$sg_var('SORT_ARTICLE')], '<span>&nbsp;</span>')['' == $this_show['title']]#
</div> </div>
<div class="clearfix"> <div class="clearfix">
<p>$this_show['rating']% <img src="$sbRoot/images/heart.png"><i>$this_show['votes'] votes</i></p> <p>$this_show['rating']%<i class="heart icon-glyph"></i><i>$this_show['votes'] votes</i></p>
#if 'url_tvdb' in $this_show and $this_show['url_tvdb']: #if 'url_tvdb' in $this_show and $this_show['url_tvdb']:
<a class="service" href="<%= anon_url(this_show['url_tvdb']) %>" onclick="window.open(this.href, '_blank'); return false;" <a class="service" href="<%= anon_url(this_show['url_tvdb']) %>" onclick="window.open(this.href, '_blank'); return false;"
title="View <span class='boldest'>tvdb</span> detail for <span style='color: rgb(66, 139, 202)'>$title_html</span>"> title="View <span class='boldest'>tvdb</span> detail for <span style='color: rgb(66, 139, 202)'>$title_html</span>">
@ -269,7 +256,7 @@
<div class="browse-add-show-holder"> <div class="browse-add-show-holder">
#if ':' in $this_show['show_id']: #if ':' in $this_show['show_id']:
<p style="line-height: 1.5; padding: 2px 5px 3px" title="<%= '%s added' % ('TVRage', 'theTVDB')['1' == this_show['show_id'][:1]] %>">In library</p> <p style="line-height:1.5;padding:2px 5px 3px" title="#echo '%s added' % $sickbeard.indexerApi(this_show['show_id'][:1]).config.get('name')#">In library</p>
#else #else
<a href="$sbRoot/home/addShows/add${browse_type}Show?indexer_id=${this_show['show_id']}&amp;showName=${urllib.quote($this_show['title'].encode("utf-8"))}" class="btn btn-xs">Add Show</a> <a href="$sbRoot/home/addShows/add${browse_type}Show?indexer_id=${this_show['show_id']}&amp;showName=${urllib.quote($this_show['title'].encode("utf-8"))}" class="btn btn-xs">Add Show</a>
#end if #end if
@ -308,4 +295,4 @@ window.setInterval('location.reload(true)', 600000); // Refresh every 10 minutes
//--> //-->
</script> </script>
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_bottom.tmpl') #include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_bottom.tmpl')

View file

@ -1,14 +1,16 @@
#import sickbeard #import sickbeard
#from sickbeard.helpers import anon_url #from sickbeard.helpers import anon_url
## ##
#set global $header = 'New Show' #set global $header = 'Add from TV info source'
#set global $title = 'New Show' #set global $title = $header
#set global $sbPath = '../..' #set global $sbPath = '../..'
#set global $statpath = '../..' #set global $statpath = '../..'
#set global $topmenu = 'home' #set global $topmenu = 'home'
<% def sg_var(varname, default=False): return getattr(sickbeard, varname, default) %>#slurp#
<% def sg_str(varname, default=''): return getattr(sickbeard, varname, default) %>#slurp#
## ##
#import os.path #import os.path
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_top.tmpl') #include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_top.tmpl')
#set indexer_count = len([$i for $i in $sickbeard.indexerApi().indexers if $sickbeard.indexerApi(i).config.get('active', False) and not $sickbeard.indexerApi(i).config.get('defunct', False)]) + 1 #set indexer_count = len([$i for $i in $sickbeard.indexerApi().indexers if $sickbeard.indexerApi(i).config.get('active', False) and not $sickbeard.indexerApi(i).config.get('defunct', False)]) + 1
@ -27,7 +29,7 @@
<h1 class="title">$title</h1> <h1 class="title">$title</h1>
#end if #end if
<image class="preload-image" style="position:absolute;top:-999px" src="$sbRoot/images/loading32<%= '-dark' if 'dark' == sickbeard.THEME_NAME else '' %>.gif" width="32" height="32" border="0"> <image class="preload-image" style="position:absolute;top:-999px" src="$sbRoot/images/loading32#echo ('', '-dark')['dark' == $sg_str('THEME_NAME', 'dark')]#.gif" width="32" height="32" border="0">
<div id="newShowPortal"> <div id="newShowPortal">
@ -40,7 +42,7 @@
<legend class="legendStep"><p>#if $use_provided_info#Using known show information#else#Find show at TV info source#end if#</p></legend> <legend class="legendStep"><p>#if $use_provided_info#Using known show information#else#Find show at TV info source#end if#</p></legend>
<div class="stepDiv"> <div class="stepDiv">
<input type="hidden" id="indexer_timeout" value="$sickbeard.INDEXER_TIMEOUT" /> <input type="hidden" id="indexer_timeout" value="$sg_var('INDEXER_TIMEOUT', 20)" />
<input type="hidden" id="indexer_count" value="$indexer_count" /> <input type="hidden" id="indexer_count" value="$indexer_count" />
#if $use_provided_info #if $use_provided_info
@ -58,7 +60,7 @@
</style> </style>
<input type="hidden" id="providedIndexer" value="$provided_indexer" /> <input type="hidden" id="providedIndexer" value="$provided_indexer" />
#end if #end if
<input type="text" id="nameToSearch" value="$default_show_name" class="form-control form-control-inline input-sm input350" /> <input type="text" id="nameToSearch" value="$default_show_name" placeholder="Enter a show name, TVDB ID, IMDb Url, or IMDb ID" class="form-control form-control-inline input-sm input350" />
&nbsp; &nbsp;
<span style="float:right"> <span style="float:right">
<select name="indexerLang" id="indexerLangSelect" class="form-control form-control-inline input-sm"> <select name="indexerLang" id="indexerLangSelect" class="form-control form-control-inline input-sm">
@ -77,7 +79,7 @@
<input class="btn btn-inline" type="button" id="searchName" value="Search" /> <input class="btn btn-inline" type="button" id="searchName" value="Search" />
</span> </span>
<br /> <br />
<p style="margin:5px 0 15px">Enter show name, TVDB ID, IMDb Url, or IMDb ID.&nbsp;&nbsp;<b>*</b>SickGear supports english, language is used for show/episode data</p> <p style="margin:5px 0 15px"><span class="add-tip">Enter show name, TVDB ID, IMDb Url, or IMDb ID.&nbsp;&nbsp;</span><b>*</b>SickGear supports english, language is used for show/episode data</p>
<div id="searchResults" style="height: 100%"></div> <div id="searchResults" style="height: 100%"></div>
#end if #end if
@ -94,7 +96,7 @@
Pre-chosen Destination Folder: <b>$provided_show_dir</b> <br /> Pre-chosen Destination Folder: <b>$provided_show_dir</b> <br />
<input type="hidden" id="fullShowPath" name="fullShowPath" value="$provided_show_dir" /><br /> <input type="hidden" id="fullShowPath" name="fullShowPath" value="$provided_show_dir" /><br />
#else #else
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_rootDirs.tmpl') #include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_rootDirs.tmpl')
#end if #end if
</div> </div>
<div style="clear:both">&nbsp;</div> <div style="clear:both">&nbsp;</div>
@ -103,7 +105,7 @@
<fieldset class="sectionwrap step-three" style="visibility:hidden"> <fieldset class="sectionwrap step-three" style="visibility:hidden">
<legend class="legendStep"><p>Set custom options</p></legend> <legend class="legendStep"><p>Set custom options</p></legend>
<div class="stepDiv"> <div class="stepDiv">
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_addShowOptions.tmpl') #include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_addShowOptions.tmpl')
</div> </div>
<div style="clear:both">&nbsp;</div> <div style="clear:both">&nbsp;</div>
</fieldset> </fieldset>
@ -128,4 +130,4 @@
</div></div> </div></div>
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_bottom.tmpl') #include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_bottom.tmpl')

View file

@ -1,14 +1,25 @@
#import sickbeard #import sickbeard
#from sickbeard.common import * #from sickbeard.common import *
#from sickbeard import subtitles #from sickbeard import subtitles
##
#set $checked = ' checked="checked"'
#set $selected = ' selected="selected"'
##
<% def sg_var(varname, default=False): return getattr(sickbeard, varname, default) %>#slurp#
<% def sg_str(varname, default=''): return getattr(sickbeard, varname, default) %>#slurp#
<div class="stepDiv linefix"> <div class="stepDiv linefix">
<div style="float:right;margin:-30px -15px 20px 15px;font-size:12px;line-height:27px;">
<span class="grey-text">To reuse options below when adding more shows&nbsp;<input class="btn btn-inline" type="button" id="saveDefaultsButton" value="Save as defaults" disabled="disabled" /></span>
</div>
<div class="field-pair"> <div class="field-pair">
<label for="statusSelect"> <label for="statusSelect">
<span class="component-title">Initial episode status</span> <span class="component-title">Initial episode status</span>
<span class="component-desc"> <span class="component-desc">
<select name="defaultStatus" id="statusSelect" class="form-control form-control-inline input-sm"> <select name="defaultStatus" id="statusSelect" class="form-control form-control-inline input-sm">
#for $curStatus in [$SKIPPED, $WANTED, $ARCHIVED, $IGNORED]: #for $curStatus in [$SKIPPED, $WANTED, $ARCHIVED, $IGNORED]:
<option value="$curStatus" #if $sickbeard.STATUS_DEFAULT == $curStatus then 'selected="selected"' else ''#>$statusStrings[$curStatus]</option> <option value="$curStatus"#if $sg_var('STATUS_DEFAULT', SKIPPED) == $curStatus then $selected else ''#>$statusStrings[$curStatus]</option>
#end for #end for
</select> </select>
<span>set the initial status of missing episodes</span> <span>set the initial status of missing episodes</span>
@ -21,10 +32,10 @@
</div> </div>
<div class="field-pair"> <div class="field-pair">
#set $qualities = $Quality.splitQuality($sickbeard.QUALITY_DEFAULT) #set $qualities = $Quality.splitQuality($sg_var('QUALITY_DEFAULT', SD))
#set global $anyQualities = $qualities[0] #set global $anyQualities = $qualities[0]
#set global $bestQualities = $qualities[1] #set global $bestQualities = $qualities[1]
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_qualityChooser.tmpl') #include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_qualityChooser.tmpl')
</div> </div>
#try: #try:
@ -33,14 +44,14 @@
<span class="component-title">From season 1 forward, set</span> <span class="component-title">From season 1 forward, set</span>
<span class="component-desc"> <span class="component-desc">
<label for="wanted_begin" style="padding-bottom:10px"> <label for="wanted_begin" style="padding-bottom:10px">
<input type="number" name="wanted_begin" id="wanted_begin" value="$sickbeard.WANTED_BEGIN_DEFAULT" class="form-control input-sm input75"> <input type="number" name="wanted_begin" id="wanted_begin" value="$sg_str('WANTED_BEGIN_DEFAULT')" class="form-control input-sm input75">
<span>episodes as wanted (10 ... 0, and where -1 is whole first season)</span> <span>episodes as wanted (10 ... 0, and where -1 is whole first season)</span>
</label> </label>
</span> </span>
<span class="component-title">From latest going back, set</span> <span class="component-title">From latest going back, set</span>
<span class="component-desc"> <span class="component-desc">
<label for="wanted_latest"> <label for="wanted_latest">
<input type="number" name="wanted_latest" id="wanted_latest" value="$sickbeard.WANTED_LATEST_DEFAULT" class="form-control input-sm input75"> <input type="number" name="wanted_latest" id="wanted_latest" value="$sg_str('WANTED_LATEST_DEFAULT')" class="form-control input-sm input75">
<span>episodes as wanted (10 ... 0, and where -1 is whole latest season)</span> <span>episodes as wanted (10 ... 0, and where -1 is whole latest season)</span>
</label> </label>
</span> </span>
@ -50,13 +61,13 @@
#pass #pass
#end try #end try
<div class="field-pair #if $sickbeard.SHOWLIST_TAGVIEW != 'custom' then 'hidden' else ''#" style="margin-top:10px"> <div class="field-pair #if $sg_str('SHOWLIST_TAGVIEW') != 'custom' then 'hidden' else ''#" style="margin-top:10px">
<label for="tag"> <label for="tag">
<span class="component-title">Place show in group</span> <span class="component-title">Place show in group</span>
<span class="component-desc"> <span class="component-desc">
<select name="tag" id="tag" class="form-control form-control-inline input-sm"> <select name="tag" id="tag" class="form-control form-control-inline input-sm">
#for $tag in $sickbeard.SHOW_TAGS: #for $tag in $sg_var('SHOW_TAGS', []):
<option value="$tag" #if $tag == $getattr(sickbeard, 'SHOW_TAG_DEFAULT', $getattr(sickbeard, 'DEFAULT_SHOW_TAG', None)) then 'selected="selected"' else ''#>$tag</option> <option value="$tag"#if $tag == $getattr(sickbeard, 'SHOW_TAG_DEFAULT', $getattr(sickbeard, 'DEFAULT_SHOW_TAG', None)) then $selected else ''#>$tag</option>
#end for #end for
</select> </select>
<span>and display on the show list page under this section</span> <span>and display on the show list page under this section</span>
@ -68,7 +79,7 @@
<label for="flatten_folders"> <label for="flatten_folders">
<span class="component-title">Flat folder structure</span> <span class="component-title">Flat folder structure</span>
<span class="component-desc"> <span class="component-desc">
<input class="cb" type="checkbox" name="flatten_folders" id="flatten_folders" #if $sickbeard.FLATTEN_FOLDERS_DEFAULT then "checked=\"checked\"" else ""# /> <input class="cb" type="checkbox" name="flatten_folders" id="flatten_folders"#if $sg_var('FLATTEN_FOLDERS_DEFAULT') then $checked else ''# />
<p>do not create sub folders</p> <p>do not create sub folders</p>
</span> </span>
</label> </label>
@ -78,18 +89,18 @@
<label for="scene"> <label for="scene">
<span class="component-title">Scene numbering</span> <span class="component-title">Scene numbering</span>
<span class="component-desc"> <span class="component-desc">
<input type="checkbox" name="scene" id="scene" #if $sickbeard.SCENE_DEFAULT then "checked=\"checked\"" else ""# /> <input type="checkbox" name="scene" id="scene"#if $sg_var('SCENE_DEFAULT') then $checked else ''# />
<p>search for episodes numbered by scene groups instead of by the TV network<span id="scene-maps-found" style="display:none" class="grey-text"> (scene numbers found)</span></p> <p>search for episodes numbered by scene groups instead of by the TV network<span id="scene-maps-found" style="display:none" class="grey-text"> (scene numbers found)</span></p>
</span> </span>
</label> </label>
</div> </div>
#if $sickbeard.USE_SUBTITLES: #if $sg_var('USE_SUBTITLES'):
<div class="field-pair alt"> <div class="field-pair alt">
<label for="subtitles"> <label for="subtitles">
<span class="component-title">Subtitles</span> <span class="component-title">Subtitles</span>
<span class="component-desc"> <span class="component-desc">
<input type="checkbox" name="subtitles" id="subtitles" #if $sickbeard.SUBTITLES_DEFAULT then "checked=\"checked\"" else ""# /> <input type="checkbox" name="subtitles" id="subtitles"#if $sg_var('SUBTITLES_DEFAULT') then $checked else ''# />
<p>download subtitles for this show</p> <p>download subtitles for this show</p>
</span> </span>
</label> </label>
@ -101,27 +112,18 @@
<label for="anime"> <label for="anime">
<span class="component-title">Show is anime</span> <span class="component-title">Show is anime</span>
<span class="component-desc"> <span class="component-desc">
<input type="checkbox" name="anime" id="anime" #if $sickbeard.ANIME_DEFAULT or $kwargs.get('is_anime') then "checked=\"checked\"" else ""# /> <input type="checkbox" name="anime" id="anime"#if $sg_var('ANIME_DEFAULT') or $kwargs.get('is_anime') then $checked else ''# />
<p>enable if this show is anime and episode releases are named ... <em class="grey-text">Show.265</em> instead of <em class="grey-text">Show.S02E03</em></p> <p>enable if this show is anime and episode releases are named ... <em class="grey-text">Show.265</em> instead of <em class="grey-text">Show.S02E03</em></p>
</span> </span>
</label> </label>
</div> </div>
#end if #end if
<div class="field-pair alt" style="margin-top:20px">
<label for="saveDefaultsButton">
<span class="component-title">Save options as defaults</span>
<span class="component-desc">
<input class="btn btn-inline" type="button" id="saveDefaultsButton" value="Save Defaults" disabled="disabled" />
<p>reuse the above options when adding more shows</p>
</span>
</label>
</div>
</div> </div>
#if $enable_anime_options #if $enable_anime_options
#import sickbeard.blackandwhitelist #import sickbeard.blackandwhitelist
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_blackwhitelist.tmpl') #include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_blackwhitelist.tmpl')
#else #else
<input type="hidden" name="anime" id="anime" value="0" /> <input type="hidden" name="anime" id="anime" value="0" />
#end if #end if

View file

@ -3,6 +3,8 @@
#import re #import re
#from sickbeard import db, sbdatetime #from sickbeard import db, sbdatetime
#from sickbeard.common import * #from sickbeard.common import *
<% def sg_var(varname, default=False): return getattr(sickbeard, varname, default) %>#slurp#
<% def sg_str(varname, default=''): return getattr(sickbeard, varname, default) %>#slurp#
## ##
</div><!-- /content --> </div><!-- /content -->
</div><!-- /contentWrapper --> </div><!-- /contentWrapper -->
@ -26,8 +28,8 @@
## ##
#set $sql_result = $my_db.select($sql_statement) #set $sql_result = $my_db.select($sql_statement)
## ##
#set $shows_total = len($sickbeard.showList) #set $shows_total = len($sg_str('showList'))
#set $shows_active = len([show for show in $sickbeard.showList if 0 == show.paused and 'Ended' != show.status]) #set $shows_active = len([show for show in $sg_str('showList') if 0 == show.paused and 'Ended' != show.status])
## ##
#if $sql_result: #if $sql_result:
#set $ep_snatched = $sql_result[0]['ep_snatched'] #set $ep_snatched = $sql_result[0]['ep_snatched']

View file

@ -0,0 +1,125 @@
#import datetime
#import sickbeard
#from sickbeard import network_timezones, sbdatetime, subtitles
#from sickbeard.common import Overview, Quality, statusStrings, ARCHIVED, UNAIRED, SUBTITLED
#from lib import subliminal
<% def sg_var(varname, default=False): return getattr(sickbeard, varname, default) %>#slurp#
<% def sg_str(varname, default=''): return getattr(sickbeard, varname, default) %>#slurp#
#######
#set $network_timezone = $network_timezones.get_network_timezone($show.network)
#set $network_time = $network_timezones.parse_time($show.airs)
#set $odd = 0
#set $fuzzydate = 'airdate'
#set $scene, $scene_anime = (False, False)
#if not $show.air_by_date and not $show.is_sports and not $show.is_anime and $show.is_scene
#set $scene = True
#elif not $show.air_by_date and not $show.is_sports and $show.is_anime and $show.is_scene
#set $scene_anime = True
#end if
#set $attr_title_ep = ('', ' (Anime #)')[$show.is_anime]
##
#set $eps = $getVar('episodes', None) or [$episode]
#for $ep in $eps
#set $ep_str = '%sx%s' % ($ep['season'], $ep['episode'])
#set $epLoc = $ep['location']
#set never_aired = 0 < int($ep['season']) and 1 == int($ep['airdate'])
<tr class="#echo ($Overview.overviewStrings[$ep_cats[$ep_str]], 'airdate-never')[$never_aired]##echo ('', ' archived')[ARCHIVED == int($ep['status'])]#">
<td class="col-checkbox">
#if $UNAIRED != int($ep['status']) and not $never_aired
<input type="checkbox" class="epCheck" id="$ep_str" name="$ep_str">
#end if
</td>
#set $nfo, $nfo_img = (('No', '-no'), ('Yes', ''))[int($ep['hasnfo'])]
#set $tbn, $tbn_img = (('No', '-no'), ('Yes', ''))[int($ep['hastbn'])]
<td align="center" class="meta"><img src="$sbRoot/images/nfo${nfo_img}.gif" alt="$nfo" title="$nfo" width="23" height="11" /><br />
<img src="$sbRoot/images/tbn${tbn_img}.gif" alt="$tbn" title="$tbn" width="23" height="11" /></td>
#if $epLoc and $show._location and $epLoc.lower().startswith($show._location.lower())
#set $epLoc = $epLoc[len($show._location)+1:]
#elif $epLoc and (not $epLoc.lower().startswith($show._location.lower()) or not $show._location)
#set $epLoc = $epLoc
#end if
#set $episode = str($ep['episode']) + ('', ' (%s)' % $ep['absolute_number'])[$show.is_anime]
#set $downloaded = ('', '<strong>file</strong> %s<br /><strong>size</strong> %s' % ($epLoc, $sickbeard.helpers.human($ep['file_size'])))['' != $epLoc and None != $epLoc]
#set $attr=(('', 'Ep # %s' % $attr_title_ep)[bool($attr_title_ep)], $downloaded)[any($downloaded)]
<td align="center">
<span style="white-space:nowrap"#if $attr# class="addQTip" title="$attr"#end if#>$episode</span>
</td>
#slurp
#if $scene
#set $dfltSeas, $dfltEpis = (0, 0) if ($ep['season'], $ep['episode']) not in $xem_numbering else $xem_numbering[($ep['season'], $ep['episode'])]
<td align="center">
<input type="text" placeholder="#echo '%sx%s' % ($dfltSeas, $dfltEpis)#" size="6" maxlength="8"
class="sceneSeasonXEpisode form-control input-scene" data-for-season="$ep['season']" data-for-episode="$ep['episode']"
id="sceneSeasonXEpisode_#echo '%s_%s_%s' % ($show.indexerid, $ep['season'], $ep['episode'])#"
title="Change the value here if scene numbering differs from the indexer episode numbering"
#if ($ep['season'], $ep['episode']) in $scene_numbering
#set $scSeas, $scEpis = $scene_numbering[($ep['season'], $ep['episode'])]
value="#echo '%sx%s' % ($scSeas, $scEpis)#"
#else
value=""
#end if
style="padding:0; text-align:center; max-width:60px">
</td>
#elif $scene_anime
#set $dfltAbsolute = 0 if $ep['absolute_number'] not in $xem_absolute_numbering else $xem_absolute_numbering[$ep['absolute_number']]
<td align="center">
<input type="text" placeholder="$dfltAbsolute" size="6" maxlength="8"
class="sceneAbsolute form-control input-scene" data-for-absolute="$ep['absolute_number']"
id="sceneAbsolute_#echo '%s_%s' % ($show.indexerid, $ep['absolute_number'])#"
title="Change the value here if scene absolute numbering differs from the indexer absolute numbering"
#if $ep['absolute_number'] in $scene_absolute_numbering
value="$scene_absolute_numbering[$ep['absolute_number']]"
#else
value=""
#end if
style="padding:0; text-align:center; max-width:60px" />
</td>
#end if
#slurp
<td class="col-name">
<img src="$sbRoot/images/info32.png" width="16" height="16" alt="" class="plotInfo#echo '%s" />' %\
('None opacity40', ('" id="plot_info_%s_%s_%s' % ($show.indexerid, $ep['season'], $ep['episode'])))[None is not $ep['description'] and '' != $ep['description']]#
#if not $ep['name'] or 'TBA' == $ep['name']#<em class="tba grey-text">TBA</em>#else#$ep['name']#end if#
</td>
<td class="col-airdate">
<span class="$fuzzydate" data-airdate="$ep['airdate']"#if $sg_var('FUZZY_DATING')# data-fulldate="$sbdatetime.sbdatetime.sbfdate(dt=$datetime.date.fromordinal($ep['airdate']), d_preset='%A, %B %d, %Y')"#end if#>#if 1 == int($ep['airdate']) then 'never' else $sbdatetime.sbdatetime.sbfdate($sbdatetime.sbdatetime.convert_to_setting($network_timezones.parse_date_time($ep['airdate'], $network_time, $network_timezone)))#</span>
</td>
#if $sg_var('USE_SUBTITLES') and $show.subtitles
<td class="col-subtitles" align="center">
#if $ep['subtitles']
#for $sub_lang in subliminal.language.language_list($ep['subtitles'].split(','))
#if '' != sub_lang.alpha2
<img src="$sbRoot/images/flags/${sub_lang.alpha2}.png" width="16" height="11" alt="${sub_lang}" />
#end if
#end for
#end if
</td>
#end if
#slurp
#set $curStatus, $curQuality = $Quality.splitCompositeStatus(int($ep['status']))
#if Quality.NONE != $curQuality
<td class="col-status">#if SUBTITLED == $curStatus#<span class="addQTip" title="$statusStrings[$curStatus]"><i class="sgicon-subtitles" style="vertical-align:middle"></i></span>#else#$statusStrings[$curStatus].replace('Downloaded', '')#end if# <span class="quality $Quality.get_quality_css($curQuality)#if $downloaded# addQTip" title="$downloaded#end if#">$Quality.qualityStrings[$curQuality]</span></td>
#else
<td class="col-status">$statusStrings[$curStatus]</td>
#end if
<td class="col-search">
#if 0 != int($ep['season'])
#if (int($ep['status']) in $Quality.SNATCHED or int($ep['status']) in $Quality.DOWNLOADED) and $sg_var('USE_FAILED_DOWNLOADS')
<a class="epRetry" id="$ep_str" name="$ep_str" href="$sbRoot/home/retryEpisode?show=$show.indexerid&amp;season=$ep['season']&amp;episode=$ep['episode']"><img src="$sbRoot/images/search16.png" height="16" alt="retry" title="Retry download" /></a>
#else
<a class="epSearch" id="$ep_str" name="$ep_str" href="$sbRoot/home/searchEpisode?show=$show.indexerid&amp;season=$ep['season']&amp;episode=$ep['episode']"><img src="$sbRoot/images/search16.png" width="16" height="16" alt="search" title="Manual search" /></a>
#end if
#end if
#slurp
#if $sg_var('USE_SUBTITLES') and $show.subtitles and len(set(str($ep['subtitles']).split(',')).intersection(set($subtitles.wantedLanguages()))) < len($subtitles.wantedLanguages()) and $ep['location']
<a class="epSubtitlesSearch" href="$sbRoot/home/searchEpisodeSubtitles?show=$show.indexerid&amp;season=$ep['season']&amp;episode=$ep['episode']"><img src="$sbRoot/images/closed_captioning.png" height="16" alt="search subtitles" title="Search subtitles" /></a>
#end if
</td>
</tr>
#end for

View file

@ -0,0 +1,59 @@
#import sickbeard
#from sickbeard.helpers import anon_url
<% def mainvar(varname, default=False): return getattr(sickbeard, varname, default) %>
<% def mainstr(varname, default=''): return getattr(sickbeard, varname, default) %>
##
#set $panel_title = {'viewart0': 'Poster <em>left</em>', 'viewart1': 'Poster <em>right</em>', 'viewart2': 'No poster',
'viewart3': 'Open gear', 'viewart4': 'Backart only',
'translucent_on': 'Translucency <em>on</em>', 'translucent_off': 'Translucency <em>off</em>',
'rateart0': 'Random (default)', 'rateart1': 'Group random',
'rateart2': 'Always display', 'rateart3': 'Avoid image',
'backart_on': 'Backart <em>on</em>', 'backart_off': 'Backart <em>off</em>',
'viewmode0': 'Regular view', 'viewmode1': 'Proview I', 'viewmode2': 'Proview II',
'viewmode3': 'Set/Save art random/avoids'}
#set $init_title_translucent = $panel_title['translucent_' + ('off', 'on')[$mainvar('DISPLAY_SHOW_BACKGROUND_TRANSLUCENT')]]
#set $init_title_backart = $panel_title['backart_' + ('off', 'on')[$mainvar('DISPLAY_SHOW_BACKGROUND') and $has_art]]
#set $init_title_view = $panel_title['viewmode%s' % ((1, 0)[not $mainvar('DISPLAY_SHOW_VIEWMODE')], $mainvar('DISPLAY_SHOW_VIEWMODE'))[$mainvar('DISPLAY_SHOW_BACKGROUND') and $has_art]]
##
<script>
config.panelTitles = $panel_title;
</script>
<script type="text/javascript" src="$sbRoot/js/livepanel.js?v=$sbPID"></script>
<div id="livepanel" class="off $getVar('fanart_panel', 'highlight2')">
<span class="over-layer0">
<span class="art-toggle oneof">
<i class="icon-glyph"></i>
<i class="icon-glyph"></i>
</span>
<span class="art-toggle-all"><i class="icon-glyph"></i></span>
<span class="art-toggle">
<i class="icon-glyph"></i>
<i class="icon-glyph rate-art"></i>
</span>
<i class="icon-glyph"></i>
<span class="art-toggle-all"><i class="icon-glyph last"></i></span>
</span>
<span id="viewmodes" class="over-layer1">
<span class="art-toggle oneof">
<a id="art-next" title="<span style='white-space:nowrap'>Next view</span>" href="#"><i class="icon-glyph"></i></a>
<a id="art-prev" title="<span style='white-space:nowrap'>Previous view</span>" href="#"><i class="icon-glyph"></i></a>
</span>
<span class="art-toggle-all"><a id="viewart" title="Poster left" href="#"><i class="icon-glyph"></i></a></span>
<span class="art-toggle">
<a id="translucent" title="$init_title_translucent" href="#"><i class="icon-glyph"></i></a>
<a id="rate-art" title="Random (default)" href="#"><i class="icon-glyph"></i></a>
</span>
#if $has_art
<a id="back-art" title="$init_title_backart" href="#"><i class="icon-glyph image"></i></a>
#else
#try
#set $link = $anon_url('https://fanart.tv/?s=', $clean_show_name, '&sect=1')
<a id="back-art" title="No art! Force full update or add one to fanart.tv if none available" href="$link" rel="noreferrer" onclick="window.open(this.href, '_blank'); return !1;"><i class="icon-glyph fatv"></i></a>
#except
<a id="back-art" title="No art available!" href="#"><i class="icon-glyph image"></i></a>
#end try
#end if
<span class="art-toggle-all"><a id="proview" title="$init_title_view" href="#"><i class="icon-glyph"></i></a></span>
</span>
</div>

View file

@ -5,7 +5,7 @@
<div class="field-pair"> <div class="field-pair">
<label for="qualityPreset" class="clearfix"> <label for="qualityPreset" class="clearfix">
#set $overall_quality = $Quality.combineQualities($anyQualities, $bestQualities) #set $overall_quality = $Quality.combineQualities($anyQualities, $bestQualities)
<span class="component-title input">Quality</span> <span class="component-title input">Quality to download</span>
<span class="component-desc"> <span class="component-desc">
#set $selected = None #set $selected = None
<select id="qualityPreset" name="quality_preset" class="form-control form-control-inline input-sm"> <select id="qualityPreset" name="quality_preset" class="form-control form-control-inline input-sm">
@ -14,7 +14,7 @@
<option value="$curPreset"#echo ('', $html_selected)[$curPreset == $overall_quality]##echo ('', ' style="padding-left:15px"')[$qualityPresetStrings[$curPreset].endswith('0p') and 'UHD' not in $qualityPresetStrings[$curPreset]]#>$qualityPresetStrings[$curPreset]</option> <option value="$curPreset"#echo ('', $html_selected)[$curPreset == $overall_quality]##echo ('', ' style="padding-left:15px"')[$qualityPresetStrings[$curPreset].endswith('0p') and 'UHD' not in $qualityPresetStrings[$curPreset]]#>$qualityPresetStrings[$curPreset]</option>
#end for #end for
</select> </select>
<span>preferred episode quality to download</span> <span>tip: select a quality then "Custom" for a default selection</span>
</span> </span>
</label> </label>
</div> </div>
@ -22,8 +22,9 @@
<div id="customQualityWrapper"> <div id="customQualityWrapper">
<div id="customQuality" class="show-if-quality-custom" style="display:none"> <div id="customQuality" class="show-if-quality-custom" style="display:none">
<div class="component-group-desc tip-text"> <div class="component-group-desc tip-text">
<p>An <em>Initial</em> quality episode must be found before an <em>Upgrade to</em> selection is considered.</p> <p>An <em class="highlight-text">Initial</em> quality downloads before any <em class="highlight-text">Upgrade to</em> selections are considered.</p>
<p>Upgrades continue until the highest selected of <em>Upgrade to</em> is matched.</p> <p>Deselect all <em class="highlight-text">Upgrade to</em> qualities to keep the first best <em class="highlight-text">Initial</em> release found.</p>
<p>All found <em class="highlight-text">Upgrade to</em> qualities download until the best.</p>
</div> </div>
<span class="component-desc"> <span class="component-desc">
@ -48,6 +49,7 @@
#end for #end for
</select><br /> </select><br />
<span>Ctrl + Click = toggle a quality</span> <span>Ctrl + Click = toggle a quality</span>
<br /><span>Ctrl + Click = toggle a quality</span>
</div> </div>
<div style="line-height:normal;padding-top:50px" id="quality-notes" class="tip-text"> <div style="line-height:normal;padding-top:50px" id="quality-notes" class="tip-text">

View file

@ -1,6 +1,8 @@
#import sickbeard #import sickbeard
#import urllib #import urllib
#from sickbeard.helpers import anon_url #from sickbeard.helpers import anon_url
<% def sg_var(varname, default=False): return getattr(sickbeard, varname, default) %>#slurp#
<% def sg_str(varname, default=''): return getattr(sickbeard, varname, default) %>#slurp#
#slurp #slurp
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
@ -35,6 +37,7 @@
<meta name="msapplication-TileColor" content="#2b5797"> <meta name="msapplication-TileColor" content="#2b5797">
<meta name="msapplication-TileImage" content="$sbRoot/images/ico/mstile-144x144.png"> <meta name="msapplication-TileImage" content="$sbRoot/images/ico/mstile-144x144.png">
<meta name="msapplication-config" content="$sbRoot/css/browserconfig.xml"> <meta name="msapplication-config" content="$sbRoot/css/browserconfig.xml">
<meta name="theme-color" content="#echo '#%s' % ('333', '15528F')['dark' == $sg_str('THEME_NAME', 'dark')]#">
<link rel="stylesheet" type="text/css" href="$sbRoot/css/lib/bootstrap.css?v=$sbPID"/> <link rel="stylesheet" type="text/css" href="$sbRoot/css/lib/bootstrap.css?v=$sbPID"/>
<link rel="stylesheet" type="text/css" href="$sbRoot/css/browser.css?v=$sbPID" /> <link rel="stylesheet" type="text/css" href="$sbRoot/css/browser.css?v=$sbPID" />
@ -42,7 +45,7 @@
<link rel="stylesheet" type="text/css" href="$sbRoot/css/lib/jquery.qtip-2.2.1.min.css?v=$sbPID"/> <link rel="stylesheet" type="text/css" href="$sbRoot/css/lib/jquery.qtip-2.2.1.min.css?v=$sbPID"/>
<link rel="stylesheet" type="text/css" href="$sbRoot/css/lib/pnotify.custom.min.css?v=$sbPID" /> <link rel="stylesheet" type="text/css" href="$sbRoot/css/lib/pnotify.custom.min.css?v=$sbPID" />
<link rel="stylesheet" type="text/css" href="$sbRoot/css/style.css?v=$sbPID"/> <link rel="stylesheet" type="text/css" href="$sbRoot/css/style.css?v=$sbPID"/>
<link rel="stylesheet" type="text/css" href="$sbRoot/css/${sickbeard.THEME_NAME}.css?v=$sbPID" /> <link rel="stylesheet" type="text/css" href="$sbRoot/css/${sg_str('THEME_NAME', 'dark')}.css?v=$sbPID" />
<script type="text/javascript" src="$sbRoot/js/lib/jquery-1.8.3.min.js?v=$sbPID"></script> <script type="text/javascript" src="$sbRoot/js/lib/jquery-1.8.3.min.js?v=$sbPID"></script>
<script type="text/javascript" src="$sbRoot/js/lib/bootstrap.min.js?v=$sbPID"></script> <script type="text/javascript" src="$sbRoot/js/lib/bootstrap.min.js?v=$sbPID"></script>
@ -63,13 +66,13 @@
<script type="text/javascript" src="$sbRoot/js/lib/jquery.confirm.js?v=$sbPID"></script> <script type="text/javascript" src="$sbRoot/js/lib/jquery.confirm.js?v=$sbPID"></script>
<script type="text/javascript" src="$sbRoot/js/script.js?v=$sbPID"></script> <script type="text/javascript" src="$sbRoot/js/script.js?v=$sbPID"></script>
<script type="text/javascript" src="$sbRoot/js/inc_top.js?v=$sbPID"></script> <script type="text/javascript" src="$sbRoot/js/inc_top.js?v=$sbPID"></script>
#if $sickbeard.FUZZY_DATING #if $sg_var('FUZZY_DATING')
<script type="text/javascript" src="$sbRoot/js/moment/moment.min.js?v=$sbPID"></script> <script type="text/javascript" src="$sbRoot/js/moment/moment.min.js?v=$sbPID"></script>
<script type="text/javascript" src="$sbRoot/js/fuzzyMoment.js?v=$sbPID"></script> <script type="text/javascript" src="$sbRoot/js/fuzzyMoment.js?v=$sbPID"></script>
#end if #end if
<script type="text/javascript" charset="utf-8"> <script type="text/javascript" charset="utf-8">
<!-- <!--
var sbRoot = '$sbRoot', anonURL = '$sickbeard.ANON_REDIRECT', themeSpinner = '#echo ('', '-dark')['dark' == $sickbeard.THEME_NAME]#', var sbRoot = '$sbRoot', anonURL = '$sg_str('ANON_REDIRECT')', themeSpinner = '#echo ('', '-dark')['dark' == $sg_str('THEME_NAME', 'dark')]#',
top_image_html = '<img src="$sbRoot/images/top.gif" width="31" height="11" alt="Jump to top" />', topmenu = '$topmenu'; top_image_html = '<img src="$sbRoot/images/top.gif" width="31" height="11" alt="Jump to top" />', topmenu = '$topmenu';
\$.SickGear = {Root: '${sbRoot}', PID: '${sbPID}'}; \$.SickGear = {Root: '${sbRoot}', PID: '${sbPID}'};
//--> //-->
@ -86,6 +89,10 @@
#except #except
#pass #pass
#end try #end try
#if not any([x in $body_attr for x in ['back-art', 'pro', 'ii']])
#set $parts = $body_attr.split('class="')
#set $body_attr = ('class="%s '.join($parts), $parts[0] + ' class="%s"')[1 == len($parts)] % {0: '', 1: 'pro', 2: 'pro ii'}.get(getattr($sickbeard, 'DISPLAY_SHOW_VIEWMODE', 0))
#end if
<body$body_attr> <body$body_attr>
<nav class="navbar navbar-default navbar-fixed-top" role="navigation"> <nav class="navbar navbar-default navbar-fixed-top" role="navigation">
<div class="container-fluid"> <div class="container-fluid">
@ -106,8 +113,22 @@
<a href="$sbRoot/home/" class="dropdown-toggle" data-toggle="dropdown" data-delay="0" tabindex="$tab#set $tab += 1#">Shows <b class="caret"></b></a> <a href="$sbRoot/home/" class="dropdown-toggle" data-toggle="dropdown" data-delay="0" tabindex="$tab#set $tab += 1#">Shows <b class="caret"></b></a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li><a href="$sbRoot/home/showlistView/" tabindex="$tab#set $tab += 1#"><i class="sgicon-home"></i>Show List</a></li> <li><a href="$sbRoot/home/showlistView/" tabindex="$tab#set $tab += 1#"><i class="sgicon-home"></i>Show List</a></li>
<li><a href="$sbRoot/home/addShows/" tabindex="$tab#set $tab += 1#"><i class="sgicon-addshow"></i>Add Shows</a></li>
<li><a href="$sbRoot/home/postprocess/" tabindex="$tab#set $tab += 1#"><i class="sgicon-postprocess"></i>Manual Post-Processing</a></li> <li><a href="$sbRoot/home/postprocess/" tabindex="$tab#set $tab += 1#"><i class="sgicon-postprocess"></i>Manual Post-Processing</a></li>
<li class="divider"></li>
<li class="menu-item-noicon opacity60">Add show...</li>
<li><a href="$sbRoot/home/addShows/new_show/" tabindex="$tab#set $tab += 1#"><i class="sgicon-addshow"></i>Search
<div class="menu-item-desc opacity60">find show at TV info source</div></a></li>
<li><a href="$sbRoot/home/addShows/trakt_default/" tabindex="$tab#set $tab += 1#"><i class="sgicon-trakt"></i>Trakt Cards
<div class="menu-item-desc opacity60">trends, tailored suggestions...</div></a></li>
<li><a href="$sbRoot/home/addShows/imdb_default/" tabindex="$tab#set $tab += 1#"><i class="sgicon-imdb"></i>IMDb Cards
<div class="menu-item-desc opacity60">popular decades, watchlists...</div></a></li>
#if $sg_var('USE_ANIDB')
<li><a href="$sbRoot/home/addShows/anime_default/" tabindex="$tab#set $tab += 1#"><div class="img-anime-16 square-16"></div>Anime Cards
<div class="menu-item-desc opacity60">browse anime to add</div></a></li>
#else
<li><a href="$sbRoot/config/anime/" class="opacity60" tabindex="$tab#set $tab += 1#"><div class="img-anime-16 square-16"></div>Anime Cards
<div class="menu-item-desc">to use, first enable AniDB here</div></a></li>
#end if
</ul> </ul>
</li> </li>
@ -127,35 +148,27 @@
<li><a href="$sbRoot/manage/manageSearches/" tabindex="$tab#set $tab += 1#"><i class="sgicon-search"></i>Manage Searches</a></li> <li><a href="$sbRoot/manage/manageSearches/" tabindex="$tab#set $tab += 1#"><i class="sgicon-search"></i>Manage Searches</a></li>
<li><a href="$sbRoot/manage/showQueueOverview/" tabindex="$tab#set $tab += 1#"><i class="sgicon-showqueue"></i>Show Queue Overview</a></li> <li><a href="$sbRoot/manage/showQueueOverview/" tabindex="$tab#set $tab += 1#"><i class="sgicon-showqueue"></i>Show Queue Overview</a></li>
<li><a href="$sbRoot/manage/episodeStatuses/" tabindex="$tab#set $tab += 1#"><i class="sgicon-episodestatus"></i>Episode Status Management</a></li> <li><a href="$sbRoot/manage/episodeStatuses/" tabindex="$tab#set $tab += 1#"><i class="sgicon-episodestatus"></i>Episode Status Management</a></li>
#if hasattr($sickbeard, 'USE_EMBY') and $sickbeard.USE_EMBY and $sickbeard.EMBY_HOST != '' and $sickbeard.EMBY_APIKEY != '' #if hasattr($sickbeard, 'USE_EMBY') and $sg_var('USE_EMBY') and $sg_str('EMBY_HOST') != '' and $sg_str('EMBY_APIKEY') != ''
<li><a href="$sbRoot/home/updateEMBY/" tabindex="$tab#set $tab += 1#"><i class="sgicon-emby"></i>Update Emby</a></li> <li><a href="$sbRoot/home/updateEMBY/" tabindex="$tab#set $tab += 1#"><i class="sgicon-emby"></i>Update Emby</a></li>
#end if #end if
#if hasattr($sickbeard, 'USE_KODI') and $sickbeard.USE_KODI and $sickbeard.KODI_HOST != '' #if hasattr($sickbeard, 'USE_KODI') and $sg_var('USE_KODI') and $sg_str('KODI_HOST') != ''
<li><a href="$sbRoot/home/updateKODI/" tabindex="$tab#set $tab += 1#"><i class="sgicon-kodi"></i>Update Kodi</a></li> <li><a href="$sbRoot/home/updateKODI/" tabindex="$tab#set $tab += 1#"><i class="sgicon-kodi"></i>Update Kodi</a></li>
#end if #end if
#if hasattr($sickbeard, 'USE_XBMC') and $sickbeard.USE_XBMC and $sickbeard.XBMC_HOST != '' #if hasattr($sickbeard, 'USE_XBMC') and $sg_var('USE_XBMC') and $sg_str('XBMC_HOST') != ''
<li><a href="$sbRoot/home/updateXBMC/" tabindex="$tab#set $tab += 1#"><i class="sgicon-xbmc"></i>Update XBMC</a></li> <li><a href="$sbRoot/home/updateXBMC/" tabindex="$tab#set $tab += 1#"><i class="sgicon-xbmc"></i>Update XBMC</a></li>
#end if #end if
#if hasattr($sickbeard, 'USE_PLEX') and $sickbeard.USE_PLEX and $sickbeard.PLEX_SERVER_HOST != '' #if hasattr($sickbeard, 'USE_PLEX') and $sg_var('USE_PLEX') and $sg_str('PLEX_SERVER_HOST') != ''
<li><a href="$sbRoot/home/updatePLEX/" tabindex="$tab#set $tab += 1#"><i class="sgicon-plex"></i>Update PLEX</a></li> <li><a href="$sbRoot/home/updatePLEX/" tabindex="$tab#set $tab += 1#"><i class="sgicon-plex"></i>Update PLEX</a></li>
#end if #end if
#if hasattr($sickbeard, 'USE_FAILED_DOWNLOADS') and $sickbeard.USE_FAILED_DOWNLOADS #if hasattr($sickbeard, 'USE_FAILED_DOWNLOADS') and $sg_var('USE_FAILED_DOWNLOADS')
<li><a href="$sbRoot/manage/failedDownloads/" tabindex="$tab#set $tab += 1#"><i class="sgicon-failed"></i>Failed Downloads</a></li> <li><a href="$sbRoot/manage/failedDownloads/" tabindex="$tab#set $tab += 1#"><i class="sgicon-failed"></i>Failed Downloads</a></li>
#end if #end if
#if hasattr($sickbeard, 'USE_SUBTITLES') and $sickbeard.USE_SUBTITLES #if hasattr($sickbeard, 'USE_SUBTITLES') and $sg_var('USE_SUBTITLES')
<li><a href="$sbRoot/manage/subtitleMissed/" tabindex="$tab#set $tab += 1#"><i class="sgicon-subtitles"></i>Missed Subtitle Management</a></li> <li><a href="$sbRoot/manage/subtitleMissed/" tabindex="$tab#set $tab += 1#"><i class="sgicon-subtitles"></i>Missed Subtitle Management</a></li>
#end if #end if
</ul> </ul>
</li> </li>
<li id="NAVerrorlogs" class="dropdown">
<a href="$sbRoot/errorlogs/" class="dropdown-toggle" data-toggle="dropdown" data-delay="0" tabindex="$tab#set $tab += 1#">$logPageTitle <b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="$sbRoot/errorlogs/" tabindex="$tab#set $tab += 1#"><i class="sgicon-errorlog"></i>View Log (Errors)</a></li>
<li><a href="$sbRoot/errorlogs/viewlog/" tabindex="$tab#set $tab += 1#"><i class="sgicon-log"></i>View Log</a></li>
</ul>
</li>
<li id="NAVconfig" class="dropdown"> <li id="NAVconfig" class="dropdown">
<a href="$sbRoot/config/" class="dropdown-toggle" data-toggle="dropdown" data-delay="0" tabindex="$tab#set $tab += 1#"><img src="$sbRoot/images/menu/system18.png" class="navbaricon hidden-xs" /><b class="caret hidden-xs"></b><span class="visible-xs">Config <b class="caret"></b></span></a> <a href="$sbRoot/config/" class="dropdown-toggle" data-toggle="dropdown" data-delay="0" tabindex="$tab#set $tab += 1#"><img src="$sbRoot/images/menu/system18.png" class="navbaricon hidden-xs" /><b class="caret hidden-xs"></b><span class="visible-xs">Config <b class="caret"></b></span></a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
@ -171,12 +184,22 @@
</li> </li>
<li class="dropdown"> <li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" data-delay="0" tabindex="$tab#set $tab += 1#"><img src="$sbRoot/images/menu/system18-2.png" class="navbaricon hidden-xs" /><b class="caret hidden-xs"></b><span class="visible-xs">System <b class="caret"></b></span></a> #set num_errors = $getVar('$log_num_errors', None)
#set $err_class = ('', ' errors ' + (len('%s' % $num_errors ) * 'n')[0:4])[any([$num_errors])]
<a href="#" class="dropdown-toggle" data-toggle="dropdown" data-delay="0" tabindex="$tab#set $tab += 1#"><img src="$sbRoot/images/menu/system18-2.png" class="navbaricon hidden-xs" /><b class="caret hidden-xs"></b><span class="visible-xs">System <b class="caret"></b></span><span class="logger bar$err_class"><i class="sgicon-warning"></i></span></a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li><a href="$sbRoot/manage/manageSearches/forceVersionCheck" tabindex="$tab#set $tab += 1#"><i class="sgicon-updatecheck"></i>Check for Updates</a></li> <li><a href="$sbRoot/manage/manageSearches/forceVersionCheck" tabindex="$tab#set $tab += 1#"><i class="sgicon-updatecheck"></i>Check for Updates</a></li>
<li><a href="$sbRoot/home/viewchanges" tabindex="$tab#set $tab += 1#"><i class="sgicon-log"></i>View Changes</a></li> <li><a href="$sbRoot/home/viewchanges" tabindex="$tab#set $tab += 1#"><i class="sgicon-changes"></i>View Changes</a></li>
<li class="divider"></li> <li class="divider"></li>
#if $sickbeard.WEB_USERNAME or $sickbeard.WEB_PASSWORD #if $err_class
<li><a href="$sbRoot/errorlogs/" tabindex="$tab#set $tab += 1#"><span class="logger item$err_class"><i class="sgicon-warning"></i></span></i>View Errors</a></li>
#end if
<li><a href="$sbRoot/errorlogs/viewlog/" tabindex="$tab#set $tab += 1#"><i class="sgicon-log"></i>View Log File</a></li>
<li class="divider"></li>
<li><a href="$sbRoot/home/addShows/import_shows/" tabindex="$tab#set $tab += 1#"><i class="sgicon-import"></i>Import
<div class="menu-item-desc opacity60">existing shows</div></a></li>
<li class="divider"></li>
#if $sg_str('WEB_USERNAME') or $sg_str('WEB_PASSWORD')
<li><a href="$sbRoot/logout" class="confirm logout" tabindex="$tab#set $tab += 1#"><i class="sgicon-logout"></i>Logout</a></li> <li><a href="$sbRoot/logout" class="confirm logout" tabindex="$tab#set $tab += 1#"><i class="sgicon-logout"></i>Logout</a></li>
#end if #end if
<li><a href="$sbRoot/home/restart/?pid=$sbPID" class="confirm restart" tabindex="$tab#set $tab += 1#"><i class="sgicon-restart"></i>Restart</a></li> <li><a href="$sbRoot/home/restart/?pid=$sbPID" class="confirm restart" tabindex="$tab#set $tab += 1#"><i class="sgicon-restart"></i>Restart</a></li>
@ -224,9 +247,9 @@
</p> </p>
</div> </div>
#end if #end if
#if $sickbeard.NEWEST_VERSION_STRING #if $sg_str('NEWEST_VERSION_STRING')
<div class="alert alert-success upgrade-notification" role="alert"> <div class="alert alert-success upgrade-notification" role="alert">
<span>$sickbeard.NEWEST_VERSION_STRING</span> <span>$sg_str('NEWEST_VERSION_STRING')</span>
</div> </div>
#end if #end if
## ##

View file

@ -1,6 +1,8 @@
#import sickbeard #import sickbeard
#from sickbeard import common #from sickbeard import common
#from sickbeard import exceptions #from sickbeard import exceptions
<% def sg_var(varname, default=False): return getattr(sickbeard, varname, default) %>#slurp#
<% def sg_str(varname, default=''): return getattr(sickbeard, varname, default) %>#slurp#
## ##
#set global $title = 'Mass Edit' #set global $title = 'Mass Edit'
#set global $header = 'Mass Edit' #set global $header = 'Mass Edit'
@ -8,7 +10,7 @@
#set global $topmenu = 'manage' #set global $topmenu = 'manage'
## ##
#import os.path #import os.path
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_top.tmpl') #include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_top.tmpl')
#if None is not $quality_value: #if None is not $quality_value:
#set $initial_quality = int($quality_value) #set $initial_quality = int($quality_value)
@ -88,7 +90,7 @@
#set $isDisabled = $isSelected #set $isDisabled = $isSelected
#if $archive_firstmatch_value##set $isDisabled = ''##else##set $isEnabled = ''##end if# #if $archive_firstmatch_value##set $isDisabled = ''##else##set $isEnabled = ''##end if#
<div class="optionWrapper clearfix"> <div class="optionWrapper clearfix">
<span class="selectTitle">End upgrade on first match</span> <span class="selectTitle">Upgrade once</span>
<div class="selectChoices"> <div class="selectChoices">
<select id="edit_archive_firstmatch" name="archive_firstmatch" class="form-control form-control-inline input-sm"> <select id="edit_archive_firstmatch" name="archive_firstmatch" class="form-control form-control-inline input-sm">
<option value="keep">&lt; keep &gt;</option> <option value="keep">&lt; keep &gt;</option>
@ -165,12 +167,12 @@
</div><br /> </div><br />
</div> </div>
<div class="optionWrapper #if $sickbeard.SHOWLIST_TAGVIEW != 'custom' then 'hidden' else ''#"> <div class="optionWrapper #if $sg_str('SHOWLIST_TAGVIEW') != 'custom' then 'hidden' else ''#">
<span class="selectTitle">Show is grouped in</span> <span class="selectTitle">Show is grouped in</span>
<div class="selectChoices"> <div class="selectChoices">
<select id="edit_tag" name="tag" class="form-control form-control-inline input-sm"> <select id="edit_tag" name="tag" class="form-control form-control-inline input-sm">
<option value="keep">&lt; keep &gt;</option> <option value="keep">&lt; keep &gt;</option>
#for $tag in $sickbeard.SHOW_TAGS: #for $tag in $sg_var('SHOW_TAGS', []):
<option value="$tag" #if $tag_value == $tag then $selected else ''#>$tag#echo ('', ' (default)')['Show List' == $tag]#</option> <option value="$tag" #if $tag_value == $tag then $selected else ''#>$tag#echo ('', ' (default)')['Show List' == $tag]#</option>
#end for #end for
</select> </select>
@ -194,4 +196,4 @@
//--> //-->
</script> </script>
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_bottom.tmpl') #include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_bottom.tmpl')

View file

@ -2,97 +2,128 @@
#from sickbeard import common #from sickbeard import common
#from sickbeard import exceptions #from sickbeard import exceptions
## ##
#set global $title = 'Test Rename ' + $show.name #set global $title = 'Media Renamer ' + $show.name
#set global $header = '<a href="' + $sbRoot + '/home/displayShow?show=%d">%s</a>' % ($show.indexerid, $show.name) #set global $header = $show.name
#set global $sbPath = '..' #set global $sbPath = '..'
#set global $topmenu = 'home' #set global $topmenu = 'home'
#set global $page_body_attr = 'rename' #set $css = $getVar('css', 'reg')
#set $has_art = $getVar('has_art', None)
#set global $page_body_attr = 'edit-show" class="' + $css
## ##
#import os.path #import os.path
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_top.tmpl') #include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_top.tmpl')
<script type="text/javascript" src="$sbRoot/js/testRename.js"></script>
<script type="text/javascript" src="$sbRoot/js/livepanel.js?v=$sbPID"></script>
#if $varExists('header') #if $varExists('header')
<h1 class="header">$header</h1> <h1 class="header"><span class="grey-text">Media Renamer&nbsp;</span>$header</h1>
#else #else
<h1 class="title">$title</h1> <h1 class="title">$title</h1>
#end if #end if
<input type="hidden" id="showID" value="$show.indexerid" /> <div id="background-container">
#if $has_art
<script type="text/javascript" src="$sbRoot/js/testRename.js"></script> <ul>
#for $k, ($image, $rating) in enumerate($fanart)
<h3>Preview of the proposed name changes</h3> <li class="#echo ' '.join((x for x in ({10:'group', 20:'fave', 30:'avoid'}.get($rating, ''), ('', 'background first-load')[$start_image == $k]) if x)) #" style="background-image:url($sbRoot/showPoster/?show=$show.indexerid&which=fanart_$image)"></li>
<blockquote> #end for
#if int($show.air_by_date) == 1 and $sickbeard.NAMING_CUSTOM_ABD: </ul>
$sickbeard.NAMING_ABD_PATTERN
#elif int($show.sports) == 1 and $sickbeard.NAMING_CUSTOM_SPORTS:
$sickbeard.NAMING_SPORTS_PATTERN
#else
$sickbeard.NAMING_PATTERN
#end if #end if
</blockquote> </div>
## <div id="config">
#set $curSeason = -1 <div id="config-content" class="linefix container">
#set $odd = False <input type="hidden" id="showID" value="$show.indexerid">
<div class="clearfix padbottom">
<div id="config-components">
<ul>
<li><a href="#core-component-group1">Preview</a></li>
</ul>
<div id="core-component-group1" class="component-group">
#if 1 == int($show.air_by_date) and $sickbeard.NAMING_CUSTOM_ABD:
#set $type = 'Air-by-date'
#set $pattern = $sickbeard.NAMING_ABD_PATTERN
#elif 1 == int($show.sports) and $sickbeard.NAMING_CUSTOM_SPORTS:
#set $type = 'Sports'
#set $pattern = $sickbeard.NAMING_SPORTS_PATTERN
#else
#set $type = 'Single episode'
#set $pattern = $sickbeard.NAMING_PATTERN
#end if
<h3>Proposed changes of existing files</h3>
<div class="component-group-desc episode-sample">
<h3>$type sample:</h3>
</div>
<div class="example" style="margin-bottom:30px">
<span class="jumbo">$pattern</span>&nbsp;<a href="$sbRoot/config/postProcessing/#core-component-group2">edit pattern</a>
</div>
<div>
<button class="btn seriesCheck">Select All Episodes</button> <button class="btn seriesCheck">Select All Episodes</button>
<button class="btn clearAll">Clear All</button> <button class="btn clearAll">Clear All</button>
</div> </div>
#set $curSeason = -1
<input type="submit" value="Rename Selected" class="btn btn-success"> <a href="$sbRoot/home/displayShow?show=$show.indexerid" class="btn btn-danger">Cancel Rename</a> #set $first_season = True
<table id="testRenameTable" class="sickbeardTable" border="0">
<table id="testRenameTable" class="sickbeardTable" border="0">
## ##
#for $cur_ep_obj in $ep_obj_list #for $cur_ep_obj in $ep_obj_list
#set $curLoc = $cur_ep_obj.location[len($cur_ep_obj.show.location)+1:] #if $curSeason != int($cur_ep_obj.season):
#set $curExt = $curLoc.split('.')[-1] #set $curSeason = int($cur_ep_obj.season)
#set $newLoc = $cur_ep_obj.proper_path() + '.' + $curExt #if not $first_season
</tbody>
#if int($cur_ep_obj.season) != $curSeason: #end if
#set $first_season = False
<thead> <thead>
<tr class="seasonheader" id="season-$cur_ep_obj.season"> <tr class="seasonheader" id="season-$cur_ep_obj.season">
<td colspan="4" class="text-left"> <td colspan="3" class="text-left">
<h2>#if 0 == int($cur_ep_obj.season) then 'Specials' else 'Season %s' % $cur_ep_obj.season#</h2> <h2>#if 0 == int($cur_ep_obj.season) then 'Specials' else 'Season %s' % $cur_ep_obj.season#</h2>
</td> </td>
</tr> </tr>
<tr class="seasoncols" id="season-$cur_ep_obj.season-cols"> <tr class="seasoncols" id="season-$cur_ep_obj.season-cols" style="line-height:26px">
<th class="col-checkbox"><input type="checkbox" class="seasonCheck" id="$cur_ep_obj.season" /></th> <th class="col-checkbox"><input type="checkbox" class="seasonCheck" id="$cur_ep_obj.season"></th>
<th class="text-nowrap">Episode</th> <th class="text-nowrap">Episode</th>
<th class="col-name">Old Location</th> <th class="col-name">Old Location / New Location</th>
<th class="col-name">New Location</th>
</tr> </tr>
</thead> </thead>
#set $curSeason = int($cur_ep_obj.season) <tbody>
#end if #end if
## ##
#set $odd = not $odd #set $curLoc = $cur_ep_obj.location[len($cur_ep_obj.show.location) + 1:]
#set $epStr = str($cur_ep_obj.season) + 'x' + str($cur_ep_obj.episode) #set $newLoc = '%s.%s' % ($cur_ep_obj.proper_path(), $curLoc.split('.')[-1])
#set $epList = sorted([cur_ep_obj.episode] + [x.episode for x in cur_ep_obj.relatedEps]) #set $epList = sorted([cur_ep_obj.episode] + [x.episode for x in cur_ep_obj.relatedEps])
#if 1 < len($epList) #if 1 < len($epList)
#set $epList = [$min($epList), $max($epList)] #set $epList = [$min($epList), $max($epList)]
#end if #end if
<tbody> <tr class="opacity60 #if $curLoc == $newLoc#good#else#wanted#end if#">
<tr class="season-$curSeason #if $curLoc == $newLoc#good#else#wanted#end if# seasonstyle"> #if $curLoc != $newLoc
#if $curLoc != $newLoc #set $epStr = '%sx%s' % ($cur_ep_obj.season, $cur_ep_obj.episode)
<td class="col-checkbox"> <td class="col-checkbox" rowspan="2" style="line-height:30px">
<input type="checkbox" class="epCheck" id="<%=str(cur_ep_obj.season) + 'x' + str(cur_ep_obj.episode)%>" name="<%=str(cur_ep_obj.season) + 'x' + str(cur_ep_obj.episode) %>"> <input type="checkbox" class="epCheck" id="$epStr" name="$epStr">
</td> </td>
#else #else
<td></td> <td rowspan="2">&nbsp;</td>
#end if #end if
<td class="col-ep text-nowrap"><%= '-'.join(map(str, epList)) %></td> <td class="col-ep text-nowrap" rowspan="2">#echo '-'.join(map(str, epList))#</td>
<td class="col-name text-left">$curLoc</td> <td style="text-align:left">now: $curLoc.replace('/', '/ ').replace('\\', ' \\ ')</td>
<td class="col-name text-left">$newLoc</td> </tr>
<tr class="#if $curLoc == $newLoc#good#else#wanted#end if#">
<td style="text-align:left">new: $newLoc.replace('/', '/ ').replace('\\', ' \\ ')<br />
test: $cur_ep_obj.proper_path().replace('/', '/ ').replace('\\', ' \\ ')</td>
</tr> </tr>
</tbody>
#end for #end for
</tbody>
</table>
</table> <div style="clear:both;margin-top:20px">
<div style="clear:both;margin-top:20px">
<input type="submit" value="Rename Selected" class="btn btn-success"> <a href="$sbRoot/home/displayShow?show=$show.indexerid" class="btn btn-danger">Cancel Rename</a> <input type="submit" value="Rename Selected" class="btn btn-success"> <a href="$sbRoot/home/displayShow?show=$show.indexerid" class="btn btn-danger">Cancel Rename</a>
</div> </div>
</div>
</div>
</div>
</div>
<input type="submit" value="Rename Selected" class="btn btn-success"> <a href="$sbRoot/home/displayShow?show=$show.indexerid" class="btn btn-danger">Cancel Rename</a>
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_bottom.tmpl') #include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_bottom.tmpl')

View file

@ -2,11 +2,14 @@
#from sickbeard import classes #from sickbeard import classes
#from sickbeard.common import * #from sickbeard.common import *
#from sickbeard.logger import reverseNames #from sickbeard.logger import reverseNames
#from sickbeard.helpers import maybe_plural
## ##
#set global $header = 'Log File' #set global $header = 'Log File'
#set global $title = 'Logs' #set global $title = 'Logs'
#set global $sbPath = '..' #set global $sbPath = '..'
#set global $topmenu = 'errorlogs' #set global $topmenu = 'errorlogs'
#set $log_level_var = None is $getVar('min_level', None) and 'minLevel' or 'min_level'
#set $log_level = $getVar($log_level_var, 20)
## ##
#import os.path #import os.path
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_top.tmpl') #include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_top.tmpl')
@ -17,13 +20,17 @@
<h1 class="title">$title</h1> <h1 class="title">$title</h1>
#end if #end if
<div class="h2footer pull-right">Minimum logging level to display: <div class="h2footer pull-right">
<select name="minLevel" id="minLevel" class="form-control form-control-inline input-sm"> <select name="minLevel" id="minLevel" class="form-control form-control-inline input-sm">
#set $levels = $reverseNames.keys() #set $levels = $reverseNames.keys()
#set void = $levels.sort(lambda x,y: cmp($reverseNames[$x], $reverseNames[$y])) #set void = $levels.sort(lambda x,y: cmp($reverseNames[$x], $reverseNames[$y]))
#set $level_count = len($levels)
#for $level in $levels #for $level in $levels
<option value="$reverseNames[$level]" #if $minLevel == $reverseNames[$level] then 'selected="selected"' else ''#>$level.title()</option> #set $level_count -= 1
#set $level_text = '%s%s' % ($level.title(), (('', ' only')[0 == $level_count], ' and the next%s level%s' % ((' ' + str($level_count), '')[1 == $level_count], maybe_plural($level_count)))[0 < $level_count])
<option value="$reverseNames[$level]"#if $log_level == $reverseNames[$level]# selected="selected" class="selected"#end if#>$level_text</option>
#end for #end for
</select> </select>
</div> </div>
@ -35,7 +42,7 @@
<!-- <!--
\$(document).ready(function(){ \$(document).ready(function(){
\$('#minLevel').change(function(){ \$('#minLevel').change(function(){
window.location.href = '$sbRoot/errorlogs/viewlog/?minLevel=' + \$(this).val() window.location.href = '$sbRoot/errorlogs/viewlog/?$log_level_var=' + \$(this).val()
}); });
window.setInterval('location.reload(true)', 600000); // Refresh every 10 minutes window.setInterval('location.reload(true)', 600000); // Refresh every 10 minutes

View file

@ -468,7 +468,7 @@ $(document).ready(function () {
at: 'top center' at: 'top center'
}, },
style: { style: {
classes: 'qtip-rounded qtip-shadow' classes: 'qtip-dark qtip-rounded qtip-shadow'
} }
}); });
$('.custom-pattern,#unpack').qtip({ $('.custom-pattern,#unpack').qtip({

View file

@ -40,7 +40,6 @@ $(document).ready(function(){
$.getJSON(sbRoot + '/config/providers/getNewznabCategories', params, $.getJSON(sbRoot + '/config/providers/getNewznabCategories', params,
function(data){ function(data){
updateNewznabCaps( data, selectedProvider ); updateNewznabCaps( data, selectedProvider );
//console.debug(data.tv_categories);
}); });
} }
@ -217,7 +216,6 @@ $(document).ready(function(){
if (rootObject.name == searchFor) { if (rootObject.name == searchFor) {
found = true; found = true;
} }
//console.log(rootObject.name + ' while searching for: ' + searchFor);
}); });
return found; return found;
}; };
@ -412,7 +410,6 @@ $(document).ready(function(){
}); });
$(this).on('click', '#newznab_cat_update', function(){ $(this).on('click', '#newznab_cat_update', function(){
//console.debug('Clicked Button');
//Maybe check if there is anything selected? //Maybe check if there is anything selected?
$('#newznab_cat option').each(function() { $('#newznab_cat option').each(function() {
@ -428,7 +425,6 @@ $(document).ready(function(){
if($(this).attr('selected') == 'selected') if($(this).attr('selected') == 'selected')
{ {
var selected_cat = $(this).val(); var selected_cat = $(this).val();
//console.debug(selected_cat);
newOptions.push({text: selected_cat, value: selected_cat}) newOptions.push({text: selected_cat, value: selected_cat})
}; };
}); });

View file

@ -1,173 +1,121 @@
$(document).ready(function () { /** @namespace $.SickGear.Root */
/** @namespace config.TVShowList */
/** @namespace config.useIMDbInfo */
/** @namespace $.SickGear.config.useFuzzy */
/** @namespace $.SickGear.config.dateFormat */
/** @namespace $.SickGear.config.timeFormat */
/** @namespace $.SickGear.config.fuzzyTrimZero */
$(document).ready(function() {
$('#sbRoot').ajaxEpSearch({'colorRow': true}); // handle the show selection dropbox
$('#pickShow').change(function() {
var val = $(this).attr('value');
if (val != 0)
window.location.href = $.SickGear.Root + '/home/displayShow?show=' + val;
});
$('#sbRoot').ajaxEpSubtitlesSearch(); $('#prevShow, #nextShow').on('click', function() {
var select$ = $('#pickShow'),
index = $.inArray(select$.find('option:selected').val()*1, config.TVShowList);
//noinspection JSUnresolvedVariable
select$.find('option[value="' + config.TVShowList[('nextShow' === $(this).attr('id')
? (index < config.TVShowList.length - 1 ? index + 1 : 0)
: (0 < index ? index - 1 : config.TVShowList.length - 1))] + '"]').attr('selected', 'selected');
select$.change();
return !1;
});
$('#seasonJump').change(function () { $('#seasonJump').change(function() {
var id = $(this).val(); var id = $(this).val();
if (id && id != 'jump') { if (id && 'jump' != id) {
$('html,body').animate({scrollTop: $(id).offset().top}, 'slow'); $('html,body').animate({scrollTop: $(id).offset().top}, 'slow');
location.hash = id; location.hash = id;
} }
$(this).val('jump'); $(this).val('jump');
}); });
$('#prevShow, #nextShow').click(function () { $('.details-plot').collapser({
var select$ = $('#pickShow'), mode: 'lines',
index = $.inArray(select$.find('option:selected').val()*1, TVShowList); truncate: 10,
select$.find('option[value="' + TVShowList[('nextShow' === $(this).attr('id') showText: '<span class="pull-right moreless"><i class="sgicon-arrowdown" style="margin-right:2px"></i>more</span>',
? (index < TVShowList.length - 1 ? index + 1 : 0) hideText: '<span class="pull-right moreless"><i class="sgicon-arrowup" style="margin-right:2px"></i>less</span>',
: (0 < index ? index - 1 : TVShowList.length - 1))] + '"]').attr('selected', 'selected'); showClass: 'show-class'
select$.change();
return false;
}); });
$('#changeStatus').click(function () { if (config.useIMDbInfo){
var sbRoot = $('#sbRoot').val(); $.fn.generateStars = function() {
var epArr = new Array() return this.each(function(i,e){$(e).html($('<span/>').width($(e).text()*12));});
};
$('.epCheck').each(function () { $('.imdbstars').generateStars();
if (this.checked == true) {
epArr.push($(this).attr('id'))
} }
$('#changeStatus').on('click', function() {
var epArr = [];
$('.epCheck').each(function() {
this.checked && epArr.push($(this).attr('id'))
}); });
if (epArr.length)
if (epArr.length == 0) window.location.href = $.SickGear.Root + '/home/setStatus?show=' + $('#showID').attr('value') +
return false; '&eps=' + epArr.join('|') + '&status=' + $('#statusSelect').attr('value');
url = sbRoot + '/home/setStatus?show=' + $('#showID').attr('value') + '&eps=' + epArr.join('|') + '&status=' + $('#statusSelect').attr('value');
window.location.href = url
});
$('.seasonCheck').click(function () {
var seasCheck = this;
var seasNo = $(seasCheck).attr('id');
$('.epCheck:visible').each(function () {
var epParts = $(this).attr('id').split('x');
if (epParts[0] == seasNo) {
this.checked = seasCheck.checked
}
});
});
var lastCheck = null;
$('.epCheck').click(function (event) {
if (!lastCheck || !event.shiftKey) {
lastCheck = this;
return;
}
var check = this;
var found = 0;
$('.epCheck').each(function () {
switch (found) {
case 2:
return false;
case 1:
this.checked = lastCheck.checked;
}
if (this == check || this == lastCheck)
found++;
});
lastClick = this;
});
// selects all visible episode checkboxes.
$('.seriesCheck').click(function () {
$('.epCheck:visible').each(function () {
this.checked = true
});
$('.seasonCheck:visible').each(function () {
this.checked = true
})
});
// clears all visible episode checkboxes and the season selectors
$('.clearAll').click(function () {
$('.epCheck:visible').each(function () {
this.checked = false
});
$('.seasonCheck:visible').each(function () {
this.checked = false
});
});
// handle the show selection dropbox
$('#pickShow').change(function () {
var sbRoot = $('#sbRoot').val();
var val = $(this).attr('value');
if (val == 0)
return;
url = sbRoot + '/home/displayShow?show=' + val;
window.location.href = url
}); });
// show/hide different types of rows when the checkboxes are changed // show/hide different types of rows when the checkboxes are changed
$("#checkboxControls input").change(function (e) { var el = $('#checkboxControls').find('input');
var whichClass = $(this).attr('id'); el.change(function() {
$(this).showHideRows(whichClass); $(this).showHideRows($(this).attr('id'));
}); });
// initially show/hide all the rows according to the checkboxes // initially show/hide all the rows according to the checkboxes
$("#checkboxControls input").each(function (e) { el.each(function() {
var status = this.checked; var status = this.checked;
$("tr." + $(this).attr('id')).each(function (e) { $('tr.' + $(this).attr('id')).each(function() {
if (status) { status && $(this).show() || $(this).hide();
$(this).show();
} else {
$(this).hide();
}
}); });
}); });
$.fn.showHideRows = function (whichClass) { $.fn.showHideRows = function(whichClass) {
var status = $('#checkboxControls > input, #' + whichClass).prop('checked'); var status = $('#checkboxControls > input, #' + whichClass).prop('checked');
$("tr." + whichClass).each(function (e) { $('tr.' + whichClass).each(function() {
if (status) { status && $(this).show() || $(this).hide();
$(this).show();
} else {
$(this).hide();
}
}); });
// hide season headers with no episodes under them // hide season headers with no episodes under them
$('tr.seasonheader').each(function () { $('tr.seasonheader').each(function() {
var numRows = 0; var numRows = 0;
var seasonNo = $(this).attr('id'); var seasonNo = $(this).attr('id');
$('tr.' + seasonNo + ' :visible').each(function () { $('tr.' + seasonNo + ' :visible').each(function() {
numRows++ numRows++
}); });
if (numRows == 0) { var el = $('#' + seasonNo + '-cols');
if (0 == numRows) {
$(this).hide(); $(this).hide();
$('#' + seasonNo + '-cols').hide() el.hide();
} else { } else {
$(this).show(); $(this).show();
$('#' + seasonNo + '-cols').show() el.show();
} }
}); });
}; };
function checkState(state){
$('.epCheck:visible, .seasonCheck:visible').prop('checked', state)
}
// selects all visible episode checkboxes.
$('.seriesCheck').on('click', function() { checkState(!0); });
// clears all visible episode checkboxes and the season selectors
$('.clearAll').on('click', function() { checkState(!1); });
function setEpisodeSceneNumbering(forSeason, forEpisode, sceneSeason, sceneEpisode) { function setEpisodeSceneNumbering(forSeason, forEpisode, sceneSeason, sceneEpisode) {
var sbRoot = $('#sbRoot').val(); var showId = $('#showID').val(), indexer = $('#indexer').val();
var showId = $('#showID').val();
var indexer = $('#indexer').val();
if (sceneSeason === '') sceneSeason = null; if ('' === sceneSeason) sceneSeason = null;
if (sceneEpisode === '') sceneEpisode = null; if ('' === sceneEpisode) sceneEpisode = null;
$.getJSON(sbRoot + '/home/setSceneNumbering', $.getJSON($.SickGear.Root + '/home/setSceneNumbering',
{ {
'show': showId, 'show': showId,
'indexer': indexer, 'indexer': indexer,
@ -176,89 +124,194 @@ $(document).ready(function () {
'sceneSeason': sceneSeason, 'sceneSeason': sceneSeason,
'sceneEpisode': sceneEpisode 'sceneEpisode': sceneEpisode
}, },
function (data) { function(data) {
// Set the values we get back // Set the values we get back
if (data.sceneSeason === null || data.sceneEpisode === null) { $('#sceneSeasonXEpisode_' + showId + '_' + forSeason + '_' + forEpisode).val(
$('#sceneSeasonXEpisode_' + showId + '_' + forSeason + '_' + forEpisode).val(''); (null === data.sceneSeason || null === data.sceneEpisode)
} ? '' : data.sceneSeason + 'x' + data.sceneEpisode);
else { if (!data.success)
$('#sceneSeasonXEpisode_' + showId + '_' + forSeason + '_' + forEpisode).val(data.sceneSeason + 'x' + data.sceneEpisode); alert(data.errorMessage ? data.errorMessage : 'Update failed.');
}
if (!data.success) {
if (data.errorMessage) {
alert(data.errorMessage);
} else {
alert('Update failed.');
}
}
} }
); );
} }
function setAbsoluteSceneNumbering(forAbsolute, sceneAbsolute) { function setAbsoluteSceneNumbering(forAbsolute, sceneAbsolute) {
var sbRoot = $('#sbRoot').val(); var showId = $('#showID').val(), indexer = $('#indexer').val();
var showId = $('#showID').val();
var indexer = $('#indexer').val();
if (sceneAbsolute === '') sceneAbsolute = null; if ('' === sceneAbsolute)
sceneAbsolute = null;
$.getJSON(sbRoot + '/home/setSceneNumbering', $.getJSON($.SickGear.Root + '/home/setSceneNumbering',
{ {
'show': showId, 'show': showId,
'indexer': indexer, 'indexer': indexer,
'forAbsolute': forAbsolute, 'forAbsolute': forAbsolute,
'sceneAbsolute': sceneAbsolute 'sceneAbsolute': sceneAbsolute
}, },
function (data) { function(data) {
// Set the values we get back // Set the values we get back
if (data.sceneAbsolute === null) { $('#sceneAbsolute_' + showId + '_' + forAbsolute).val(
$('#sceneAbsolute_' + showId + '_' + forAbsolute).val(''); (null === data.sceneAbsolute) ? '' : data.sceneAbsolute);
} if (!data.success)
else { alert(data.errorMessage ? data.errorMessage : 'Update failed.');
$('#sceneAbsolute_' + showId + '_' + forAbsolute).val(data.sceneAbsolute);
}
if (!data.success) {
if (data.errorMessage) {
alert(data.errorMessage);
} else {
alert('Update failed.');
}
}
} }
); );
} }
$('.sceneSeasonXEpisode').change(function () { function qTips(select$){
select$.each(function() {
$(this).qtip({
show: {solo:true},
position: {viewport:$(window), my:'left center', adjust:{y:-10, x:2}},
style: {classes:'qtip-dark qtip-rounded qtip-shadow qtip-maxwidth'}
});
});
}
qTips($('.addQTip'));
function table_init(table$) {
$('#sbRoot').ajaxEpSearch({'colorRow': true});
$('#sbRoot').ajaxEpSubtitlesSearch();
if ($.SickGear.config.useFuzzy) {
fuzzyMoment({
containerClass: '.airdate',
dateHasTime: !1,
dateFormat: $.SickGear.config.dateFormat,
timeFormat: $.SickGear.config.timeFormat,
trimZero: $.SickGear.config.fuzzyTrimZero
});
}
table$.each(function (i, obj) {
$(obj).has('tbody.collapse tr').tablesorter({
widgets: ['zebra'],
selectorHeaders: '> thead tr.tablesorter-headerRow th',
textExtraction: {
'.tablesorter-ep-num': function(node) {
var n = /(\d+)\)?$/img.exec(''+$(node).find('span').text()); return (null == n ? '' : n[1]); },
'.tablesorter-ep-scene': function(node) {
var n = $(node).find('input'); return n.val() || n.attr('placeholder'); },
'.tablesorter-airdate': function(node) { return $(node).find('span').attr('data-airdate') || ''; }
},
headers: {
'.tablesorter-no-sort': {sorter: !1, parser: !1},
'.tablesorter-ep-num': {sorter: 'digit'},
'.tablesorter-airdate': {sorter: 'digit'}
}
});
$(obj).find('.seasonCheck').on('click', function() {
var seasCheck = this, seasNo = $(seasCheck).attr('id');
$(obj).find('.epCheck:visible').each(function() {
var epParts = $(this).attr('id').split('x');
if (epParts[0] == seasNo)
this.checked = seasCheck.checked
});
});
var lastCheck = null;
$(obj).find('.epCheck').on('click', function(event) {
if (!lastCheck || !event.shiftKey) {
lastCheck = this;
return;
}
var check = this, found = 0;
$(obj).find('.epCheck').each(function() {
switch(found) {
case 2:
return !1;
case 1:
this.checked = lastCheck.checked;
}
(this == check || this == lastCheck) && found++;
});
lastCheck = this;
});
qTips($(obj).find('.addQTip'));
plotter($(obj).find('.plotInfo'));
$(obj).find('.sceneSeasonXEpisode').change(function() {
// Strip non-numeric characters // Strip non-numeric characters
$(this).val($(this).val().replace(/[^0-9xX]*/g, '')); $(this).val($(this).val().replace(/[^0-9xX]*/g, ''));
var forSeason = $(this).attr('data-for-season');
var forEpisode = $(this).attr('data-for-episode');
var showId = $('#showID').val();
var indexer = $('#indexer').val();
//var sceneEpisode = $('#sceneEpisode_' + showId + '_' + forSeason +'_' + forEpisode).val(); var forSeason = $(this).attr('data-for-season'),
var m = $(this).val().match(/^(\d+)x(\d+)$/i); forEpisode = $(this).attr('data-for-episode'),
var sceneSeason = null, sceneEpisode = null; m = $(this).val().match(/^(\d+)x(\d+)$/i),
if (m) { sceneSeason = m && m[1] || null, sceneEpisode = m && m[2] || null;
sceneSeason = m[1];
sceneEpisode = m[2];
}
setEpisodeSceneNumbering(forSeason, forEpisode, sceneSeason, sceneEpisode); setEpisodeSceneNumbering(forSeason, forEpisode, sceneSeason, sceneEpisode);
}); });
$('.sceneAbsolute').change(function () { $(obj).find('.sceneAbsolute').change(function() {
// Strip non-numeric characters // Strip non-numeric characters
$(this).val($(this).val().replace(/[^0-9xX]*/g, '')); $(this).val($(this).val().replace(/[^0-9xX]*/g, ''));
var forAbsolute = $(this).attr('data-for-absolute');
var showId = $('#showID').val();
var indexer = $('#indexer').val();
var m = $(this).val().match(/^(\d{1,3})$/i); var forAbsolute = $(this).attr('data-for-absolute'),
var sceneAbsolute = null; m = $(this).val().match(/^(\d{1,3})$/i),
if (m) { sceneAbsolute = m && m[1] || null;
sceneAbsolute = m[1];
}
setAbsoluteSceneNumbering(forAbsolute, sceneAbsolute); setAbsoluteSceneNumbering(forAbsolute, sceneAbsolute);
}); });
});
}
table_init($('.sickbeardTable'));
$.SickGear.season = [];
$.SickGear.run = !1;
$('button[id*="showseason-"]').on('click', function() {
var that = this, this$ = $('#' + this.id), table$ = this$.parents('.sickbeardTable');
if (0 < table$.find('tbody').find('tr').length) {
table$.toggleClass('open');
} else {
table$.find('span.images').toggleClass('hide');
this$.toggleClass('hide');
function fetchSeason() {
if (0 == $.SickGear.season.length)
return;
var season = $.SickGear.season[0];
$.SickGear.season.shift();
$.getJSON($.SickGear.Root + '/home/display_season', {'show': $('#showID').val(), 'season': season},
function(data) {
if (!data.success) {
alert('Season listing failed.');
} else {
table$.find('tbody').html(data.success);
table_init(table$);
}
table$.toggleClass('open');
this$.toggleClass('hide');
table$.find('span.images').toggleClass('hide');
fetchSeason()
}
);
}
$.SickGear.season.push(this.id);
var result = [];
$.each($.SickGear.season, function(i, e) {
if (-1 == $.inArray(e, result)) result.push(e);
});
$.SickGear.season = result;
if (!$.SickGear.run && 1 == $.SickGear.season.length) $.SickGear.run = !0 && fetchSeason();
}
return !1;
});
$('button.allseasons').on('click', function() {
$('table.sickbeardTable:not(.display-season)').each(function() {
$(this).find('button[id*="showseason-"]').click();
});
var liveStates = $('#display-show');
return liveStates.toggleClass('min'), $.get($.SickGear.Root + '/live_panel/?allseasons='
+ String.prototype.toLowerCase.apply(+liveStates.hasClass('min'))), !1;
});
}); });

View file

@ -1,3 +1,4 @@
/** @namespace $.SickGear.Root */
/** @namespace config.showLang */ /** @namespace config.showLang */
/** @namespace config.showIsAnime */ /** @namespace config.showIsAnime */
/*globals $, config, sbRoot, generate_bwlist*/ /*globals $, config, sbRoot, generate_bwlist*/
@ -7,13 +8,13 @@ $(document).ready(function () {
$('#location').fileBrowser({title: 'Select Show Location'}); $('#location').fileBrowser({title: 'Select Show Location'});
function htmlFlag(lang) { function htmlFlag(lang) {
return ' class="flag" style="background-image:url(' + sbRoot + '/images/flags/' + lang + '.png)"' return ' class="flag" style="background-image:url(' + $.SickGear.Root + '/images/flags/' + lang + '.png)"'
} }
$.getJSON(sbRoot + '/home/addShows/getIndexerLanguages', {}, function (data) { $.getJSON($.SickGear.Root + '/home/addShows/getIndexerLanguages', {}, function (data) {
var result = '', currentLangAdded = '', selected = ' selected="selected"'; var result = '', currentLangAdded = '', selected = ' selected="selected"';
if (0 == data.results.length) { if (!data.results.length) {
result = '<option value="' + config.showLang + '"' + selected + htmlFlag(config.showLang) + '>' result = '<option value="' + config.showLang + '"' + selected + htmlFlag(config.showLang) + '>'
+ config.showLang + '</option>'; + config.showLang + '</option>';
} else { } else {
@ -47,13 +48,13 @@ $(document).ready(function () {
return allExceptions return allExceptions
} }
$('#submit').click(function () { $('#submit').on('click', function () {
$('#exceptions_list').val(getExceptions()); $('#exceptions_list').val(getExceptions());
if (config.showIsAnime) if (config.showIsAnime)
generate_bwlist(); generate_bwlist();
}); });
$('#addSceneName').click(function () { $('#addSceneName').on('click', function () {
var elSceneName = $('#SceneName'), elSceneNameSeason = $('#SceneNameSeason'), var elSceneName = $('#SceneName'), elSceneNameSeason = $('#SceneNameSeason'),
sceneEx = elSceneName.val(), sceneExSeason = elSceneNameSeason.val(); sceneEx = elSceneName.val(), sceneExSeason = elSceneNameSeason.val();
@ -72,7 +73,7 @@ $(document).ready(function () {
return option.appendTo($('#exceptions_list')); return option.appendTo($('#exceptions_list'));
}); });
$('#removeSceneName').click(function () { $('#removeSceneName').on('click', function () {
$('#exceptions_list').find('option:selected').remove(); $('#exceptions_list').find('option:selected').remove();
$(this).toggle_SceneException(); $(this).toggle_SceneException();
@ -99,8 +100,8 @@ $(document).ready(function () {
uncheck(elABD); uncheck(elSports); uncheck(elABD); uncheck(elSports);
if (config.showIsAnime) { $('#blackwhitelist').fadeIn('fast', 'linear'); } return !0; } if (config.showIsAnime) { $('#blackwhitelist').fadeIn('fast', 'linear'); } return !0; }
function isScene() { uncheck(elABD); uncheck(elSports); } function isScene() { uncheck(elABD); uncheck(elSports); }
function isABD() { uncheck(elAnime); uncheck(elScene); $('#blackwhitelist').fadeOut('fast', 'linear'); } function isABD() { uncheck(elAnime); uncheck(elScene); $('#blackwhitelist, #anime-options').fadeOut('fast', 'linear'); }
function isSports() { uncheck(elAnime); uncheck(elScene); $('#blackwhitelist').fadeOut('fast', 'linear'); } function isSports() { uncheck(elAnime); uncheck(elScene); $('#blackwhitelist, #anime-options').fadeOut('fast', 'linear'); }
if (checked(elAnime)) { isAnime(); } if (checked(elAnime)) { isAnime(); }
if (checked(elScene)) { isScene(); } if (checked(elScene)) { isScene(); }

View file

@ -21,7 +21,6 @@ function initActions() {
$('#SubMenu a:contains("General")').addClass('btn').html('<i class="sgicon-config"></i>General'); $('#SubMenu a:contains("General")').addClass('btn').html('<i class="sgicon-config"></i>General');
$('#SubMenu a:contains("Episode Status")').addClass('btn').html('<i class="sgicon-episodestatus"></i>Episode Status Management'); $('#SubMenu a:contains("Episode Status")').addClass('btn').html('<i class="sgicon-episodestatus"></i>Episode Status Management');
$('#SubMenu a:contains("Missed Subtitle")').addClass('btn').html('<i class="sgicon-subtitles"></i>Missed Subtitles'); $('#SubMenu a:contains("Missed Subtitle")').addClass('btn').html('<i class="sgicon-subtitles"></i>Missed Subtitles');
$('#SubMenu a[href$="/home/addShows/"]').addClass('btn').html('<i class="sgicon-addshow"></i>Add Show');
$('#SubMenu a:contains("Processing")').addClass('btn').html('<i class="sgicon-postprocess"></i>Post-Processing'); $('#SubMenu a:contains("Processing")').addClass('btn').html('<i class="sgicon-postprocess"></i>Post-Processing');
$('#SubMenu a:contains("Manage Searches")').addClass('btn').html('<i class="sgicon-search"></i>Manage Searches'); $('#SubMenu a:contains("Manage Searches")').addClass('btn').html('<i class="sgicon-search"></i>Manage Searches');
$('#SubMenu a:contains("Manage Torrents")').addClass('btn').html('<i class="sgicon-bittorrent"></i>Manage Torrents'); $('#SubMenu a:contains("Manage Torrents")').addClass('btn').html('<i class="sgicon-bittorrent"></i>Manage Torrents');
@ -40,4 +39,5 @@ $(document).ready(function(){
initActions(); initActions();
$('#NAV' + topmenu).addClass('active'); $('#NAV' + topmenu).addClass('active');
$('.dropdown-toggle').dropdownHover(); $('.dropdown-toggle').dropdownHover();
(/undefined/i.test(document.createElement('input').placeholder)) && $('body').addClass('no-placeholders');
}); });

View file

@ -5,7 +5,7 @@ a.o.afterShow.call(a.e,a)};e.isFunction(a.o.beforeShow)&&a.o.beforeShow.call(a.e
k.animate({height:h},f,function(){k.height("auto");g()});c.removeClass(a.o.hideClass).addClass(a.o.showClass);break;case "block":a.blockMode(c,"show",f,g)}a.status=1;if(!0==a.o.lockHide)return c.find("[data-ctrl]").remove(),"";if("block"==a.mode)c.off("click.coll").on("click.coll",function(b){b.preventDefault();a.hide(c)});else 0!=c.find("[data-ctrl]").length||e.isFunction(a.o.controlBtn)||c.append(a.ctrlHtml),a.ctrlBtn=e.isFunction(a.o.controlBtn)?a.o.controlBtn.call(a.e):e(c.find("[data-ctrl]")), k.animate({height:h},f,function(){k.height("auto");g()});c.removeClass(a.o.hideClass).addClass(a.o.showClass);break;case "block":a.blockMode(c,"show",f,g)}a.status=1;if(!0==a.o.lockHide)return c.find("[data-ctrl]").remove(),"";if("block"==a.mode)c.off("click.coll").on("click.coll",function(b){b.preventDefault();a.hide(c)});else 0!=c.find("[data-ctrl]").length||e.isFunction(a.o.controlBtn)||c.append(a.ctrlHtml),a.ctrlBtn=e.isFunction(a.o.controlBtn)?a.o.controlBtn.call(a.e):e(c.find("[data-ctrl]")),
a.ctrlBtn.off("click.coll").on("click.coll",function(b){b.preventDefault();a.hide(c)}).html(a.o.hideText)},hide:function(b,f){var a=this,c=e(b);"undefined"===typeof f&&(f=a.o.speed);var g=function(){e.isFunction(a.o.afterHide)&&a.o.afterHide.call(a.e,a)};e.isFunction(a.o.beforeHide)&&a.o.beforeHide.call(a.e,a);c.find("[data-ctrl]").remove();switch(a.mode){case "chars":var d=e.trim(c.text());a.remaining.chars=d.length-a.o.truncate;d.length>a.o.truncate&&(c.data("tHTML",c.html()),d=a.pad(d.slice(0, a.ctrlBtn.off("click.coll").on("click.coll",function(b){b.preventDefault();a.hide(c)}).html(a.o.hideText)},hide:function(b,f){var a=this,c=e(b);"undefined"===typeof f&&(f=a.o.speed);var g=function(){e.isFunction(a.o.afterHide)&&a.o.afterHide.call(a.e,a)};e.isFunction(a.o.beforeHide)&&a.o.beforeHide.call(a.e,a);c.find("[data-ctrl]").remove();switch(a.mode){case "chars":var d=e.trim(c.text());a.remaining.chars=d.length-a.o.truncate;d.length>a.o.truncate&&(c.data("tHTML",c.html()),d=a.pad(d.slice(0,
a.o.truncate),d.slice(a.o.truncate,d.length)),c.html(d).removeClass(a.o.showClass).addClass(a.o.hideClass),g());break;case "words":d=e.trim(c.text());d=d.split(" ");a.remaining.words=d.length-a.o.truncate;d.length>a.o.truncate&&(c.data("tHTML",c.html()),d=a.pad(d.slice(0,a.o.truncate).join(" "),d.slice(a.o.truncate,d.length).join(" ")),c.html(d).removeClass(a.o.showClass).addClass(a.o.hideClass),g());break;case "lines":0==c.children("div").length&&c.wrapInner("<div>");d=c.children("div").css("height", a.o.truncate),d.slice(a.o.truncate,d.length)),c.html(d).removeClass(a.o.showClass).addClass(a.o.hideClass),g());break;case "words":d=e.trim(c.text());d=d.split(" ");a.remaining.words=d.length-a.o.truncate;d.length>a.o.truncate&&(c.data("tHTML",c.html()),d=a.pad(d.slice(0,a.o.truncate).join(" "),d.slice(a.o.truncate,d.length).join(" ")),c.html(d).removeClass(a.o.showClass).addClass(a.o.hideClass),g());break;case "lines":0==c.children("div").length&&c.wrapInner("<div>");d=c.children("div").css("height",
"");d.html(d.text());var h=d.height();"undefined"===typeof c.data("lHeight")?(temp=d.clone(),lHeight=temp.text("a").insertAfter(d).height(),c.data("lHeight",lHeight),d.next().remove()):lHeight=c.data("lHeight");lines=h/lHeight;a.remaining.lines=lines-a.o.truncate;0<a.remaining.lines&&(d.css("overflow","hidden"),d.animate({height:lHeight*a.o.truncate},f).data("tHeight",h),c.removeClass(a.o.showClass).addClass(a.o.hideClass),0!=c.find("[data-ctrl]").length||e.isFunction(a.o.controlBtn)||c.append(a.ctrlHtml), "");t=d.html();d.html(d.text());var h=d.height();"undefined"===typeof c.data("lHeight")?(temp=d.clone(),lHeight=temp.text("a").insertAfter(d).height(),c.data("lHeight",lHeight),d.next().remove()):lHeight=c.data("lHeight");lines=h/lHeight;a.remaining.lines=lines-a.o.truncate;d.html(t);0<a.remaining.lines&&(d.css("overflow","hidden"),d.animate({height:lHeight*a.o.truncate},f).data("tHeight",h),c.removeClass(a.o.showClass).addClass(a.o.hideClass),0!=c.find("[data-ctrl]").length||e.isFunction(a.o.controlBtn)||c.append(a.ctrlHtml),
g());break;case "block":a.blockMode(c,"hide",f,g)}a.status=0;"block"==a.mode?c.unbind("click.coll").bind("click.coll",function(b){b.preventDefault();a.show(c)}):(a.ctrlBtn=e.isFunction(a.o.controlBtn)?a.o.controlBtn.call(a.e):e(c.find("[data-ctrl]")),a.ctrlBtn.off("click.coll").on("click.coll",function(b){b.preventDefault();a.show(c)}).html(a.o.showText),g=a.o.showText,d={chars:["character","characters"],words:["word","words"],lines:["lines","lines"]},g=g.replace("%s",a.remaining[a.mode]+(1==a.remaining[a.mode]? g());break;case "block":a.blockMode(c,"hide",f,g)}a.status=0;"block"==a.mode?c.unbind("click.coll").bind("click.coll",function(b){b.preventDefault();a.show(c)}):(a.ctrlBtn=e.isFunction(a.o.controlBtn)?a.o.controlBtn.call(a.e):e(c.find("[data-ctrl]")),a.ctrlBtn.off("click.coll").on("click.coll",function(b){b.preventDefault();a.show(c)}).html(a.o.showText),g=a.o.showText,d={chars:["character","characters"],words:["word","words"],lines:["lines","lines"]},g=g.replace("%s",a.remaining[a.mode]+(1==a.remaining[a.mode]?
" "+d[a.mode][0]:" "+d[a.mode][1])),a.ctrlBtn.html(g))},pad:function(b,f){return b+'<span class="coll-ellipsis">'+this.o.ellipsis+"</span>"+(e.isFunction(this.o.ctrlBtn)?"":this.ctrlHtml)+'<span class="coll-hidden" style="display:none">'+f+"</span>"},blockMode:function(b,f,a,c){var g=["fadeOut","slideUp","fadeIn","slideDown"],d="fade"==this.o.effect?0:1,g="hide"==f?g[d]:g[d+2];if(e.isFunction(this.o.target))this.o.target.call(this.e)[g](a,c);else if(e.fn[this.o.target])e(b)[this.o.target]()[g](a, " "+d[a.mode][0]:" "+d[a.mode][1])),a.ctrlBtn.html(g))},pad:function(b,f){return b+'<span class="coll-ellipsis">'+this.o.ellipsis+"</span>"+(e.isFunction(this.o.ctrlBtn)?"":this.ctrlHtml)+'<span class="coll-hidden" style="display:none">'+f+"</span>"},blockMode:function(b,f,a,c){var g=["fadeOut","slideUp","fadeIn","slideDown"],d="fade"==this.o.effect?0:1,g="hide"==f?g[d]:g[d+2];if(e.isFunction(this.o.target))this.o.target.call(this.e)[g](a,c);else if(e.fn[this.o.target])e(b)[this.o.target]()[g](a,
c);"show"==f?(b.removeClass(this.o.showClass).addClass(this.o.hideClass),this.o.changeText&&b.text(this.o.hideText)):(b.removeClass(this.o.hideClass).addClass(this.o.showClass),this.o.changeText&&b.text(this.o.showText))},reInit:function(b){b.find("[data-ctrl]").remove();b.html(this.e.data("oCnt"));0==this.status?this.hide(b,0):this.show(b,0)}};e.fn.collapser=function(b){return this.each(function(){e.data(this,"collapser")||e.data(this,"collapser",new l(this,b))})}})(jQuery,window,document); c);"show"==f?(b.removeClass(this.o.showClass).addClass(this.o.hideClass),this.o.changeText&&b.text(this.o.hideText)):(b.removeClass(this.o.hideClass).addClass(this.o.showClass),this.o.changeText&&b.text(this.o.showText))},reInit:function(b){b.find("[data-ctrl]").remove();b.html(this.e.data("oCnt"));0==this.status?this.hide(b,0):this.show(b,0)}};e.fn.collapser=function(b){return this.each(function(){e.data(this,"collapser")||e.data(this,"collapser",new l(this,b))})}})(jQuery,window,document);

View file

@ -10,7 +10,7 @@ var scrolltotop={
//scrollto: Keyword (Integer, or "Scroll_to_Element_ID"). How far to scroll document up when control is clicked on (0=top). //scrollto: Keyword (Integer, or "Scroll_to_Element_ID"). How far to scroll document up when control is clicked on (0=top).
setting: {startline:100, scrollto: 0, scrollduration:1000, fadeduration:[500, 100]}, setting: {startline:100, scrollto: 0, scrollduration:1000, fadeduration:[500, 100]},
controlHTML: top_image_html,//set in inc_top.tmpl so it can be $sbRooted controlHTML: top_image_html,//set in inc_top.tmpl so it can be $sbRooted
controlattrs: {offsetx:10, offsety:10}, //offset of control relative to right/ bottom of window corner controlattrs: {offsetx:5, offsety:5}, //offset of control relative to right/ bottom of window corner
anchorkeyword: '#top', //Enter href value of HTML anchors on the page that should also act as "Scroll Up" links anchorkeyword: '#top', //Enter href value of HTML anchors on the page that should also act as "Scroll Up" links
state: {isvisible:false, shouldvisible:false}, state: {isvisible:false, shouldvisible:false},
@ -56,7 +56,7 @@ var scrolltotop={
mainobj.$body=(window.opera)? (document.compatMode=="CSS1Compat"? $('html') : $('body')) : $('html,body') mainobj.$body=(window.opera)? (document.compatMode=="CSS1Compat"? $('html') : $('body')) : $('html,body')
mainobj.$control=$('<div id="topcontrol">'+mainobj.controlHTML+'</div>') mainobj.$control=$('<div id="topcontrol">'+mainobj.controlHTML+'</div>')
.css({position:mainobj.cssfixedsupport? 'fixed' : 'absolute', bottom:mainobj.controlattrs.offsety, right:mainobj.controlattrs.offsetx, opacity:0, cursor:'pointer'}) .css({position:mainobj.cssfixedsupport? 'fixed' : 'absolute', bottom:mainobj.controlattrs.offsety, right:mainobj.controlattrs.offsetx, opacity:0, cursor:'pointer'})
.attr({title:'Scroll Back to Top'}) .attr({title:'Scroll to Top'})
.click(function(){mainobj.scrollup(); return false}) .click(function(){mainobj.scrollup(); return false})
.appendTo('body') .appendTo('body')
if (document.all && !window.XMLHttpRequest && mainobj.$control.text()!='') //loose check for IE6 and below, plus whether control contains any text if (document.all && !window.XMLHttpRequest && mainobj.$control.text()!='') //loose check for IE6 and below, plus whether control contains any text

296
gui/slick/js/livepanel.js Normal file
View file

@ -0,0 +1,296 @@
/** @namespace $.SickGear.Root */
/** @namespace config.hasArt */
/** @namespace config.panelTitles */
$(document).ready(function() {
var panel$ = $('#livepanel'),
pTitle = config.panelTitles || [],
isEpisodeView = !!$('#episode-view').length,
liveStates$ = $(isEpisodeView ? '#episode-view' : '#display-show'),
jqTooltipUsed = /(?!undefined)/i.test(typeof($('body').tooltip)),
group = 'group', fave = 'fave', avoid = 'avoid', ratingVerbs = [group, fave, avoid].join(' ');
panel$.removeClass('off');
$('#viewart').on('click', function() {
var state = 0, on = '', result = !1;
if (isEpisodeView) {
if (isSet('open-gear')) {
state = 4; on = 'viewart';
} else if (!isSet('viewart')) {
state = 3; on = 'open-gear';
}
} else if (!isSet('back-art')) {
if (!isSet('poster-right')) {
state = 1; on = 'poster-right';
}
} else if (isSet('open-gear')) {
state = 4; on = 'viewart';
} else if (isSet('poster-off')) {
state = 3; on = 'open-gear';
} else if (isSet('poster-right')) {
state = 2; on = 'poster-off';
} else if (!isSet('viewart')) {
state = 1; on = 'poster-right';
}
liveStates$.removeClass('poster-right poster-off open-gear viewart').addClass(on);
refreshTitles($(this).attr('id'));
send('viewart=' + state);
var container = [];
$.each($('[id^=day]'), function() { container.push($('#' + $(this).attr('id'))) });
$.each(container, function() { $(this).isotope('layout') });
return result;
});
$('#back-art,#translucent').on('click', function() {
var result = !1,
highlight = panel$.hasClass('highlight-off') ||
panel$.hasClass('highlight2') && panel$.removeClass('highlight2').addClass('highlight1') ||
panel$.hasClass('highlight1') && panel$.removeClass('highlight1').addClass('highlight') ||
panel$.removeClass('highlight').addClass('highlight-off');
if (config.hasArt) {
var elid = $(this).attr('id');
liveStates$.toggleClass(elid);
refreshTitles(elid);
send(elid.replace('-', '') + '=' + String.prototype.toLowerCase.apply(+isSet(elid)));
}
return result;
});
$('#proview').on('click', function() {
var state = 0, on = 'reg', result = !1;
if (!isEpisodeView && isSet('viewart')) {
liveStates$.toggleClass('allart');
} else {
if (isSet('reg')) {
state = 1; on = 'pro';
} else if(isSet('back-art') && !isSet('allart')) {
if (isSet('ii')) {
state = 3; on = 'pro ii allart';
} else if (isSet('pro')) {
state = 2; on = 'pro ii';
}
}
liveStates$.removeClass('reg pro ii allart').addClass(on);
send('viewmode=' + state);
}
maybeBackground();
refreshTitles($(this).attr('id'));
return result;
});
/*
* back art related
*/
function maybeArrows() {
var backArts$ = $('#background-container'), result = !0;
if (isSet('allart')
|| (!isSet(fave) &&
(1 < backArts$.find('li.' + group).length ||
(1 != backArts$.find('li.' + group).length && 1 < backArts$.find('li').not('.' + group + ',.' + avoid).length)))
|| (isEpisodeView &&
1 < (backArts$.find('li.' + group).length + backArts$.find('li.' + fave).length +
backArts$.find('li').not('.' + group + ',.' + avoid).length))) {
liveStates$.removeClass('oneof');
} else {
liveStates$.addClass('oneof');
}
return result
}
function setArt(dir) {
var backArts$ = $('#background-container'), curArt$ = backArts$.find('li.background'),
faveArt$ = backArts$.find('li.' + fave), result = !0,
newArt$, init = !1, noArt = function(el) { return /undefined/i.test(typeof(el.css('background-image'))); },
viewable = !isSet('allart') && !!backArts$.find('li.' + group).length ? (isEpisodeView ? '': '.' + group) : '',
mayAvoid = !isSet('allart') ? '.' + avoid : '.showall',
artBefore$ = curArt$.prevAll(viewable).not(mayAvoid),
artAfter$ = curArt$.nextAll(viewable).not(mayAvoid);
switch (dir) {
case 'next':
if (noArt(newArt$ = artAfter$.first()) && noArt(newArt$ = artBefore$.last())
&& noArt(newArt$ = curArt$))
newArt$ = null;
break;
case 'prev':
if (noArt(newArt$ = artBefore$.first()) && noArt(newArt$ = artAfter$.last())
&& noArt(newArt$ = curArt$))
newArt$ = null;
break;
case 'init':
init = !0;
if (noArt(newArt$ = curArt$))
newArt$ = null;
break;
case fave:
newArt$ = faveArt$;
break;
}
if (!init || (null == newArt$))
curArt$.addClass('background-rem').removeClass('background')
.fadeOut(800, 'linear', function() {$(this).removeClass('background-rem')});
if (null !== newArt$) {
newArt$.addClass('background').fadeIn(800, 'linear', function () {
$(this).removeClass('first-load')
});
liveStates$.removeClass(ratingVerbs).addClass(
newArt$.hasClass(group) && group || newArt$.hasClass(fave) && fave || newArt$.hasClass(avoid) && avoid || '');
}
maybeArrows();
refreshTitles();
return result;
}
setArt('init');
function maybeBackground() {
var backArts$ = $('#background-container'), result = !0;
if (isSet('allart')) {
if (!backArts$.find('li.background').length) {
backArts$.find('li').first().hide().addClass('background')
.fadeIn(400, 'linear', function() {$(this).removeClass('first-load')});
}
} else {
if (backArts$.find('li.' + fave).not('.background').length) {
setArt(fave);
} else if (!!backArts$.find('li.' + avoid).length
&& backArts$.find('li.' + avoid).length == backArts$.find('li').length) {
backArts$.find('li.' + avoid).fadeOut(800, 'linear', function () {
$(this).removeClass('background')
});
} else if (backArts$.find('li.background.' + avoid).length) {
setArt('next');
}
}
maybeArrows();
return result;
}
$('#art-next,#art-prev').on('click', function() {
return (!(setArt('art-prev' === $(this).attr('id') ? 'prev' : 'next')));
});
function key(e, kCode){
return e.hasOwnProperty('ctrlKey') && e.ctrlKey && e.hasOwnProperty('altKey') && e.altKey && (kCode == e.which)
}
$(document).on('keyup', function(e) {
var left = key(e, 37), up = key(e, 38), right = key(e, 39), down = key(e, 40),
s = key(e, 83), a = key(e, 65), f = key(e, 70), g = key(e, 71);
return (
(!isSet('oneof') && ((left && setArt('prev')) || (right && setArt('next'))))
|| (s && liveStates$.toggleClass('allart') && maybeBackground() && refreshTitles('proview'))
|| (g && setGroup()) || (up && setGroup() && (!isSet('allart') && $('#viewart').click() || !0))
|| (a && setAvoid()) || (down && setAvoid() && (!isSet('allart') && $('#translucent').click() || !0))
|| (f && setFave())
);
});
function rate(state, rating) {
var result = !0;
if (isSet('allart')) {
var rated = rating && isSet(rating);
liveStates$.removeClass(ratingVerbs);
if (rated) {
state = 0;
rating = '';
} else
liveStates$.addClass(rating);
var curArt$ = $('#background-container').find('li.background'),
art = /\?([^"]+)"/i.exec(curArt$.css('background-image'));
if (null != art) {
send('rate=' + state + '&' + art[1]);
curArt$.removeClass().addClass((!!rating.length ? rating + ' ' : '') + 'background');
}
maybeBackground();
refreshTitles('rate-art');
}
return result;
}
function setAvoid() {return rate(30, avoid);}
function setFave() {return rate(20, fave);}
function setGroup() {return rate(10, group);}
function setRnd() {return rate(0, '');}
$('#rate-art').on('click', function() {
return isSet('allart') &&
((isSet(fave) && setAvoid()) || (isSet(group) && setFave()) || (!isSet(avoid) && setGroup()) || setRnd()) || !0;
});
/*
* support functions
*/
function isSet(name) {return liveStates$.hasClass(name)}
function send(value) {
return $.get($.SickGear.Root + '/live_panel/?' + value + '&pg=' + (isEpisodeView ? 'ev' : 'ds'))}
if (jqTooltipUsed) {
panel$.find('a[title]').tooltip({placement: 'top', html: !0});
}
function refreshTitle(target$, title, refreshAll) {
return jqTooltipUsed
? target$.attr('data-original-title', title.replace(/<[\/]?em>/g, '')).tooltip('fixTitle') && refreshAll //|| target$.tooltip('show')
: target$.attr('title', title);
}
function refreshTitles(id) {
if (!$('#livepanel').length) return;
var refreshAll = /undefined/i.test(typeof(id)), elId = !refreshAll && id.replace('#', '') || id, result = !0;
if ('viewart' === elId || refreshAll) {
refreshTitle($('#viewart'),
isSet('poster-right') ? pTitle['viewart1']
: (isSet('back-art') ?
(isSet('viewart') ? pTitle['viewart4']
: (isSet('open-gear') ? pTitle['viewart3']
: (isSet('poster-off') ? pTitle['viewart2']
: (isEpisodeView ? pTitle['viewmode0'] : pTitle['viewart0']))))
: (isEpisodeView ? pTitle['viewmode0'] : pTitle['viewart0'])),
refreshAll);
}
if ('translucent' === elId || refreshAll) {
refreshTitle($('#translucent'), isSet('translucent') ? pTitle['translucent_on'] : pTitle['translucent_off'],
refreshAll);
}
if (config.hasArt && ('back-art' === elId || refreshAll)) {
refreshTitle($('#back-art'), isSet('back-art') ? pTitle['backart_on'] : pTitle['backart_off'],
refreshAll);
}
if ('rate-art' === elId || refreshAll) {
refreshTitle($('#rate-art'),
isSet(avoid) ? pTitle['rateart3']
: (isSet(fave) ? pTitle['rateart2']
: (isSet(group) ? pTitle['rateart1']
: pTitle['rateart0'])),
refreshAll);
}
if ('proview' === elId || refreshAll) {
refreshTitle($('#proview'),
isSet('back-art') ?
(isSet('allart') ? pTitle['viewmode3']
: (isSet('ii') ? pTitle['viewmode2']
: (isSet('pro') ? pTitle['viewmode1']
: pTitle['viewmode0'])))
: (isSet('pro') ? pTitle['viewmode1']
: pTitle['viewmode0']),
refreshAll);
}
return result;
}
refreshTitles();
});

View file

@ -1,5 +1,5 @@
$(function () { var plotter = function(select$) {
$('.plotInfo, .plot-daybyday').each(function () { select$.each(function() {
var match = $(this).attr('id').match(/^plot(?:_info_|-)((\d+)_(\d+)[_x](\d+))$/); var match = $(this).attr('id').match(/^plot(?:_info_|-)((\d+)_(\d+)[_x](\d+))$/);
var showName = $('#show-' + match[1]).attr('data-rawname'); var showName = $('#show-' + match[1]).attr('data-rawname');
$(this).qtip({ $(this).qtip({
@ -7,7 +7,7 @@ $(function () {
text: function(event, api) { text: function(event, api) {
// deferred object ensuring the request is only made once // deferred object ensuring the request is only made once
$.ajax({ $.ajax({
url: $('#sbRoot').val() + '/home/plotDetails', url: $.SickGear.Root + '/home/plotDetails',
type: 'GET', type: 'GET',
data: { data: {
show: match[2], show: match[2],
@ -39,8 +39,9 @@ $(function () {
} }
}, },
style: { style: {
classes: 'qtip-rounded qtip-shadow' classes: 'qtip-dark qtip-rounded qtip-shadow'
} }
}); });
}); });
}); };
$(function () { plotter($('.plotInfo, .plot-daybyday')) });

View file

@ -19,7 +19,7 @@ $(function () {
} }
}, },
style: { style: {
classes: 'qtip-rounded qtip-shadow' classes: 'qtip-dark qtip-rounded qtip-shadow'
} }
}); });
}); });

View file

@ -6,7 +6,7 @@ $(function () {
text: function(event, api) { text: function(event, api) {
// deferred object ensuring the request is only made once // deferred object ensuring the request is only made once
$.ajax({ $.ajax({
url: $('#sbRoot').val() + '/home/sceneExceptions', url: $.SickGear.Root + '/home/sceneExceptions',
type: 'GET', type: 'GET',
data: { data: {
show: match[1] show: match[1]
@ -35,7 +35,7 @@ $(function () {
} }
}, },
style: { style: {
classes: 'qtip-rounded qtip-shadow' classes: 'qtip-dark qtip-rounded qtip-shadow'
} }
}); });
}); });

98
lib/fanart/__init__.py Normal file
View file

@ -0,0 +1,98 @@
__author__ = 'Andrea De Marco <24erre@gmail.com>'
__version__ = '1.4.0'
__classifiers__ = [
'Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers',
'License :: OSI Approved :: Apache Software License',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Topic :: Internet :: WWW/HTTP',
'Topic :: Software Development :: Libraries',
]
__copyright__ = "2012, %s " % __author__
__license__ = """
Copyright %s.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either expressed or implied.
See the License for the specific language governing permissions and
limitations under the License.
""" % __copyright__
__docformat__ = 'restructuredtext en'
__doc__ = """
:abstract: Python interface to fanart.tv API
:version: %s
:author: %s
:contact: http://z4r.github.com/
:date: 2012-04-04
:copyright: %s
""" % (__version__, __author__, __license__)
def values(obj):
return [v for k, v in obj.__dict__.iteritems() if not k.startswith('_')]
BASEURL = 'http://webservice.fanart.tv/v3/%s/%s?api_key=%s'
class FORMAT(object):
JSON = 'JSON'
XML = 'XML'
PHP = 'PHP'
class WS(object):
MUSIC = 'music'
MOVIE = 'movies'
TV = 'tv'
class TYPE(object):
ALL = 'all'
class TV(object):
ART = 'clearart'
LOGO = 'clearlogo'
CHARACTER = 'characterart'
THUMB = 'tvthumb'
SEASONTHUMB = 'seasonthumb'
BACKGROUND = 'showbackground'
HDLOGO = 'hdtvlogo'
HDART = 'hdclearart'
POSTER = 'tvposter'
BANNER = 'tvbanner'
class MUSIC(object):
DISC = 'cdart'
LOGO = 'musiclogo'
BACKGROUND = 'artistbackground'
COVER = 'albumcover'
THUMB = 'artistthumb'
class MOVIE(object):
ART = 'movieart'
LOGO = 'movielogo'
DISC = 'moviedisc'
POSTER = 'movieposter'
BACKGROUND = 'moviebackground'
HDLOGO = 'hdmovielogo'
HDART = 'hdmovieclearart'
BANNER = 'moviebanner'
THUMB = 'moviethumb'
FORMAT_LIST = values(FORMAT)
WS_LIST = values(WS)
TYPE_LIST = values(TYPE.MUSIC) + values(TYPE.TV) + values(TYPE.MOVIE) + [TYPE.ALL]
MUSIC_TYPE_LIST = values(TYPE.MUSIC) + [TYPE.ALL]
TV_TYPE_LIST = values(TYPE.TV) + [TYPE.ALL]
MOVIE_TYPE_LIST = values(TYPE.MOVIE) + [TYPE.ALL]

86
lib/fanart/core.py Normal file
View file

@ -0,0 +1,86 @@
import requests
import re
import lib.fanart as fanart
from sickbeard.bs4_parser import BS4Parser
from .errors import ResponseFanartError
class Request(object):
def __init__(self, apikey, tvdb_id, ws=fanart.WS.TV):
self._apikey = apikey
self._tvdb_id = tvdb_id
self._ws = ws
self._response = None
self._web_url = 'https://fanart.tv/series/%s'
self._assets_url = 'https://assets.fanart.tv'
def __str__(self):
return fanart.BASEURL % (self._ws, self._tvdb_id, self._apikey)
def response(self):
try:
response = requests.get(str(self))
rjson = response.json()
image_type = u'showbackground'
rhtml = self.scrape_web(image_type)
if not isinstance(rjson, dict) and 0 == len(rhtml[image_type]):
raise Exception(response.text)
if 0 < len(rhtml[image_type]):
items = {image_type: []}
for item1 in rhtml[image_type]:
use_item = True
for k, item2 in enumerate(rjson[image_type] or []):
if '00' == item2['lang']: # adjust api data of no language to a default
rjson[image_type][k]['lang'] = u'en'
if item1['id'] == item2['id']:
use_item = False
break
if use_item:
items[image_type] += [item1]
rjson[image_type] += items[image_type]
return rjson
except Exception as e:
raise ResponseFanartError(str(e))
def scrape_web(self, image_type):
try:
data = requests.get(self._web_url % self._tvdb_id)
if not data:
return
with BS4Parser(data.text, features=['html5lib', 'permissive']) as html:
ul_item = html.find('ul', attrs={'class': image_type})
if ul_item:
li_items = ul_item('li')
if li_items:
image_urls = {image_type: []}
for li_item in li_items:
image_id = None
item = li_item.find('a', attrs={'class': 'download'}).get('href')
if item:
match = re.search(r'image=(\d+)', item, re.I)
if match:
image_id = u'%s' % match.group(1)
item = li_item.find('a', attrs={'rel': image_type}).get('href')
image_url = (u'%s%s' % (self._assets_url, item), None)[None is item]
item = li_item.find('div', attrs={'class': 'votes'}).get_text()
image_likes = (item, 0)[None is item]
item = li_item.find('div', attrs={'class': 'metrics'}).get_text()
image_lang = u'None found'
if item:
match = re.search(r'Language:\s*(\w+)', item, re.I)
if match:
image_lang = u'%s' % (match.group(1)[0:2:].lower(), 'en')['None' == match.group(1)]
if not (None is image_id or None is image_url):
image_urls[image_type].append({u'id': image_id, u'url': image_url, u'likes': image_likes, u'lang': image_lang})
return image_urls
except Exception, e:
pass

11
lib/fanart/errors.py Normal file
View file

@ -0,0 +1,11 @@
class FanartError(Exception):
def __str__(self):
return ', '.join(map(str, self.args))
def __repr__(self):
name = self.__class__.__name__
return '%s%r' % (name, self.args)
class ResponseFanartError(FanartError):
pass

46
lib/fanart/immutable.py Normal file
View file

@ -0,0 +1,46 @@
class Immutable(object):
_mutable = False
def __setattr__(self, name, value):
if self._mutable or name == '_mutable':
super(Immutable, self).__setattr__(name, value)
else:
raise TypeError("Can't modify immutable instance")
def __delattr__(self, name):
if self._mutable:
super(Immutable, self).__delattr__(name)
else:
raise TypeError("Can't modify immutable instance")
def __eq__(self, other):
return hash(self) == hash(other)
def __hash__(self):
return hash(repr(self))
def __repr__(self):
return '%s(%s)' % (
self.__class__.__name__,
', '.join(['{0}={1}'.format(k, repr(v)) for k, v in self])
)
def __iter__(self):
l = self.__dict__.keys()
l.sort()
for k in l:
if not k.startswith('_'):
yield k, getattr(self, k)
@staticmethod
def mutablemethod(f):
def func(self, *args, **kwargs):
if isinstance(self, Immutable):
old_mutable = self._mutable
self._mutable = True
res = f(self, *args, **kwargs)
self._mutable = old_mutable
else:
res = f(self, *args, **kwargs)
return res
return func

68
lib/fanart/items.py Normal file
View file

@ -0,0 +1,68 @@
import json
import os
import requests
from .core import Request
from .immutable import Immutable
class LeafItem(Immutable):
KEY = NotImplemented
@Immutable.mutablemethod
def __init__(self, id, url, likes):
self.id = int(id)
self.url = url
self.likes = int(likes)
self._content = None
@classmethod
def from_dict(cls, resource):
return cls(**dict([(str(k), v) for k, v in resource.iteritems()]))
@classmethod
def extract(cls, resource):
return [cls.from_dict(i) for i in resource.get(cls.KEY, {})]
@Immutable.mutablemethod
def content(self):
if not self._content:
self._content = requests.get(self.url).content
return self._content
def __str__(self):
return self.url
class ResourceItem(Immutable):
WS = NotImplemented
request_cls = Request
@classmethod
def from_dict(cls, map):
raise NotImplementedError
@classmethod
def get(cls, id):
map = cls.request_cls(
apikey=os.environ.get('FANART_APIKEY'),
tvdb_id=id,
ws=cls.WS
).response()
return cls.from_dict(map)
def json(self, **kw):
return json.dumps(
self,
default=lambda o: dict([(k, v) for k, v in o.__dict__.items() if not k.startswith('_')]),
**kw
)
class CollectableItem(Immutable):
@classmethod
def from_dict(cls, key, map):
raise NotImplementedError
@classmethod
def collection_from_dict(cls, map):
return [cls.from_dict(k, v) for k, v in map.iteritems()]

108
lib/fanart/tv.py Normal file
View file

@ -0,0 +1,108 @@
import lib.fanart as fanart
from .items import LeafItem, Immutable, ResourceItem
__all__ = (
'CharacterItem',
'ArtItem',
'LogoItem',
'BackgroundItem',
'SeasonItem',
'ThumbItem',
'HdLogoItem',
'HdArtItem',
'PosterItem',
'BannerItem',
'TvShow',
)
class TvItem(LeafItem):
@Immutable.mutablemethod
def __init__(self, id, url, likes, lang):
super(TvItem, self).__init__(id, url, likes)
self.lang = lang
class SeasonedTvItem(TvItem):
@Immutable.mutablemethod
def __init__(self, id, url, likes, lang, season):
super(SeasonedTvItem, self).__init__(id, url, likes, lang)
self.season = 0 if season == 'all' else int(season or 0)
class CharacterItem(TvItem):
KEY = fanart.TYPE.TV.CHARACTER
class ArtItem(TvItem):
KEY = fanart.TYPE.TV.ART
class LogoItem(TvItem):
KEY = fanart.TYPE.TV.LOGO
class BackgroundItem(SeasonedTvItem):
KEY = fanart.TYPE.TV.BACKGROUND
class SeasonItem(SeasonedTvItem):
KEY = fanart.TYPE.TV.SEASONTHUMB
class ThumbItem(TvItem):
KEY = fanart.TYPE.TV.THUMB
class HdLogoItem(TvItem):
KEY = fanart.TYPE.TV.HDLOGO
class HdArtItem(TvItem):
KEY = fanart.TYPE.TV.HDART
class PosterItem(TvItem):
KEY = fanart.TYPE.TV.POSTER
class BannerItem(TvItem):
KEY = fanart.TYPE.TV.BANNER
class TvShow(ResourceItem):
WS = fanart.WS.TV
@Immutable.mutablemethod
def __init__(self, name, tvdbid, backgrounds, characters, arts, logos, seasons, thumbs, hdlogos, hdarts, posters,
banners):
self.name = name
self.tvdbid = tvdbid
self.backgrounds = backgrounds
self.characters = characters
self.arts = arts
self.logos = logos
self.seasons = seasons
self.thumbs = thumbs
self.hdlogos = hdlogos
self.hdarts = hdarts
self.posters = posters
self.banners = banners
@classmethod
def from_dict(cls, resource):
assert len(resource) == 1, 'Bad Format Map'
name, resource = resource.items()[0]
return cls(
name=name,
tvdbid=resource['thetvdb_id'],
backgrounds=BackgroundItem.extract(resource),
characters=CharacterItem.extract(resource),
arts=ArtItem.extract(resource),
logos=LogoItem.extract(resource),
seasons=SeasonItem.extract(resource),
thumbs=ThumbItem.extract(resource),
hdlogos=HdLogoItem.extract(resource),
hdarts=HdArtItem.extract(resource),
posters=PosterItem.extract(resource),
banners=BannerItem.extract(resource),
)

View file

@ -19,21 +19,19 @@ class TMDB:
url = TMDB.url + '/' + path + '?api_key=' + TMDB.api_key url = TMDB.url + '/' + path + '?api_key=' + TMDB.api_key
if method == 'GET': if method == 'GET':
headers = {'Accept': 'application/json'} headers = {'Accept': 'application/json'}
content = requests.get(url, params=params, headers=headers).content content = requests.get(url, params=params, headers=headers, verify=False).content
elif method == 'POST': elif method == 'POST':
for key in params.keys(): for key in params.keys():
url += '&' + key + '=' + params[key] url += '&' + key + '=' + params[key]
headers = {'Content-Type': 'application/json', \ headers = {'Content-Type': 'application/json', \
'Accept': 'application/json'} 'Accept': 'application/json'}
content = requests.post(url, data=json.dumps(json_body), \ content = requests.post(url, data=json.dumps(json_body), headers=headers, verify=False).content
headers=headers).content
elif method == 'DELETE': elif method == 'DELETE':
for key in params.keys(): for key in params.keys():
url += '&' + key + '=' + params[key] url += '&' + key + '=' + params[key]
headers = {'Content-Type': 'application/json', \ headers = {'Content-Type': 'application/json', \
'Accept': 'application/json'} 'Accept': 'application/json'}
content = requests.delete(url, data=json.dumps(json_body), \ content = requests.delete(url, data=json.dumps(json_body), headers=headers, verify=False).content
headers=headers).content
else: else:
raise Exception('method: ' + method + ' not supported.') raise Exception('method: ' + method + ' not supported.')
response = json.loads(content.decode('utf-8')) response = json.loads(content.decode('utf-8'))

View file

@ -35,7 +35,7 @@ import uuid
sys.path.insert(1, os.path.abspath('../lib')) sys.path.insert(1, os.path.abspath('../lib'))
from sickbeard import helpers, encodingKludge as ek from sickbeard import helpers, encodingKludge as ek
from sickbeard import db, logger, naming, metadata, providers, scene_exceptions, scene_numbering, \ from sickbeard import db, image_cache, logger, naming, metadata, providers, scene_exceptions, scene_numbering, \
scheduler, auto_post_processer, search_queue, search_propers, search_recent, search_backlog, \ scheduler, auto_post_processer, search_queue, search_propers, search_recent, search_backlog, \
show_queue, show_updater, subtitles, traktChecker, version_checker, indexermapper, classes show_queue, show_updater, subtitles, traktChecker, version_checker, indexermapper, classes
from sickbeard.config import CheckSection, check_setting_int, check_setting_str, ConfigMigrator, minimax from sickbeard.config import CheckSection, check_setting_int, check_setting_str, ConfigMigrator, minimax
@ -423,13 +423,28 @@ EMAIL_LIST = None
GUI_NAME = None GUI_NAME = None
DEFAULT_HOME = None DEFAULT_HOME = None
FANART_LIMIT = None
FANART_PANEL = None
FANART_RATINGS = {}
HOME_LAYOUT = None HOME_LAYOUT = None
HISTORY_LAYOUT = None POSTER_SORTBY = None
POSTER_SORTDIR = None
DISPLAY_SHOW_VIEWMODE = 0
DISPLAY_SHOW_BACKGROUND = False
DISPLAY_SHOW_BACKGROUND_TRANSLUCENT = False
DISPLAY_SHOW_VIEWART = 0
DISPLAY_SHOW_MINIMUM = True
DISPLAY_SHOW_SPECIALS = False DISPLAY_SHOW_SPECIALS = False
EPISODE_VIEW_VIEWMODE = 0
EPISODE_VIEW_BACKGROUND = False
EPISODE_VIEW_BACKGROUND_TRANSLUCENT = False
EPISODE_VIEW_LAYOUT = None EPISODE_VIEW_LAYOUT = None
EPISODE_VIEW_SORT = None EPISODE_VIEW_SORT = None
EPISODE_VIEW_DISPLAY_PAUSED = False EPISODE_VIEW_DISPLAY_PAUSED = False
EPISODE_VIEW_POSTERS = True
EPISODE_VIEW_MISSED_RANGE = None EPISODE_VIEW_MISSED_RANGE = None
HISTORY_LAYOUT = None
FUZZY_DATING = False FUZZY_DATING = False
TRIM_ZERO = False TRIM_ZERO = False
DATE_PRESET = None DATE_PRESET = None
@ -437,8 +452,6 @@ TIME_PRESET = None
TIME_PRESET_W_SECONDS = None TIME_PRESET_W_SECONDS = None
TIMEZONE_DISPLAY = None TIMEZONE_DISPLAY = None
THEME_NAME = None THEME_NAME = None
POSTER_SORTBY = None
POSTER_SORTDIR = None
USE_SUBTITLES = False USE_SUBTITLES = False
SUBTITLES_LANGUAGES = [] SUBTITLES_LANGUAGES = []
@ -462,6 +475,7 @@ REQUIRE_WORDS = ''
CALENDAR_UNPROTECTED = False CALENDAR_UNPROTECTED = False
TMDB_API_KEY = 'edc5f123313769de83a71e157758030b' TMDB_API_KEY = 'edc5f123313769de83a71e157758030b'
FANART_API_KEY = '3728ca1a2a937ba0c93b6e63cc86cecb'
# to switch between staging and production TRAKT environment # to switch between staging and production TRAKT environment
TRAKT_STAGING = False TRAKT_STAGING = False
@ -518,13 +532,16 @@ def initialize(console_logging=True):
# Views # Views
global GUI_NAME, HOME_LAYOUT, POSTER_SORTBY, POSTER_SORTDIR, DISPLAY_SHOW_SPECIALS, \ global GUI_NAME, HOME_LAYOUT, POSTER_SORTBY, POSTER_SORTDIR, DISPLAY_SHOW_SPECIALS, \
EPISODE_VIEW_LAYOUT, EPISODE_VIEW_SORT, EPISODE_VIEW_DISPLAY_PAUSED, \ EPISODE_VIEW_LAYOUT, EPISODE_VIEW_SORT, EPISODE_VIEW_DISPLAY_PAUSED, \
EPISODE_VIEW_MISSED_RANGE, HISTORY_LAYOUT EPISODE_VIEW_MISSED_RANGE, EPISODE_VIEW_POSTERS, FANART_PANEL, FANART_RATINGS, \
EPISODE_VIEW_VIEWMODE, EPISODE_VIEW_BACKGROUND, EPISODE_VIEW_BACKGROUND_TRANSLUCENT, \
DISPLAY_SHOW_VIEWMODE, DISPLAY_SHOW_BACKGROUND, DISPLAY_SHOW_BACKGROUND_TRANSLUCENT, \
DISPLAY_SHOW_VIEWART, DISPLAY_SHOW_MINIMUM, DISPLAY_SHOW_SPECIALS, HISTORY_LAYOUT
# Gen Config/Misc # Gen Config/Misc
global LAUNCH_BROWSER, UPDATE_SHOWS_ON_START, SHOW_UPDATE_HOUR, \ global LAUNCH_BROWSER, UPDATE_SHOWS_ON_START, SHOW_UPDATE_HOUR, \
TRASH_REMOVE_SHOW, TRASH_ROTATE_LOGS, ACTUAL_LOG_DIR, LOG_DIR, INDEXER_TIMEOUT, ROOT_DIRS, \ TRASH_REMOVE_SHOW, TRASH_ROTATE_LOGS, ACTUAL_LOG_DIR, LOG_DIR, INDEXER_TIMEOUT, ROOT_DIRS, \
VERSION_NOTIFY, AUTO_UPDATE, UPDATE_FREQUENCY, NOTIFY_ON_UPDATE VERSION_NOTIFY, AUTO_UPDATE, UPDATE_FREQUENCY, NOTIFY_ON_UPDATE
# Gen Config/Interface # Gen Config/Interface
global THEME_NAME, DEFAULT_HOME, SHOWLIST_TAGVIEW, SHOW_TAGS, \ global THEME_NAME, DEFAULT_HOME, FANART_LIMIT, SHOWLIST_TAGVIEW, SHOW_TAGS, \
HOME_SEARCH_FOCUS, USE_IMDB_INFO, IMDB_ACCOUNTS, SORT_ARTICLE, FUZZY_DATING, TRIM_ZERO, \ HOME_SEARCH_FOCUS, USE_IMDB_INFO, IMDB_ACCOUNTS, SORT_ARTICLE, FUZZY_DATING, TRIM_ZERO, \
DATE_PRESET, TIME_PRESET, TIME_PRESET_W_SECONDS, TIMEZONE_DISPLAY, \ DATE_PRESET, TIME_PRESET, TIME_PRESET_W_SECONDS, TIMEZONE_DISPLAY, \
WEB_USERNAME, WEB_PASSWORD, CALENDAR_UNPROTECTED, USE_API, API_KEY, WEB_PORT, WEB_LOG, \ WEB_USERNAME, WEB_PASSWORD, CALENDAR_UNPROTECTED, USE_API, API_KEY, WEB_PORT, WEB_LOG, \
@ -611,6 +628,8 @@ def initialize(console_logging=True):
'pyTivo', 'NMA', 'Pushalot', 'Pushbullet', 'Subtitles'): 'pyTivo', 'NMA', 'Pushalot', 'Pushbullet', 'Subtitles'):
CheckSection(CFG, stanza) CheckSection(CFG, stanza)
update_config = False
# wanted branch # wanted branch
BRANCH = check_setting_str(CFG, 'General', 'branch', '') BRANCH = check_setting_str(CFG, 'General', 'branch', '')
@ -645,6 +664,14 @@ def initialize(console_logging=True):
THEME_NAME = check_setting_str(CFG, 'GUI', 'theme_name', 'dark') THEME_NAME = check_setting_str(CFG, 'GUI', 'theme_name', 'dark')
GUI_NAME = check_setting_str(CFG, 'GUI', 'gui_name', 'slick') GUI_NAME = check_setting_str(CFG, 'GUI', 'gui_name', 'slick')
DEFAULT_HOME = check_setting_str(CFG, 'GUI', 'default_home', 'home') DEFAULT_HOME = check_setting_str(CFG, 'GUI', 'default_home', 'home')
FANART_LIMIT = check_setting_int(CFG, 'GUI', 'fanart_limit', 3)
FANART_PANEL = check_setting_str(CFG, 'GUI', 'fanart_panel', 'highlight2')
FANART_RATINGS = check_setting_str(CFG, 'GUI', 'fanart_ratings', None)
if None is not FANART_RATINGS:
FANART_RATINGS = ast.literal_eval(FANART_RATINGS or '{}')
else:
FANART_RATINGS = ast.literal_eval(check_setting_str(CFG, 'GUI', 'backart_ratings', None) or '{}')
update_config |= image_cache.ImageCache().clean_fanart()
USE_IMDB_INFO = bool(check_setting_int(CFG, 'GUI', 'use_imdb_info', 1)) USE_IMDB_INFO = bool(check_setting_int(CFG, 'GUI', 'use_imdb_info', 1))
IMDB_ACCOUNTS = CFG.get('GUI', []).get('imdb_accounts', [IMDB_DEFAULT_LIST_ID, IMDB_DEFAULT_LIST_NAME]) IMDB_ACCOUNTS = CFG.get('GUI', []).get('imdb_accounts', [IMDB_DEFAULT_LIST_ID, IMDB_DEFAULT_LIST_NAME])
HOME_SEARCH_FOCUS = bool(check_setting_int(CFG, 'General', 'home_search_focus', HOME_SEARCH_FOCUS)) HOME_SEARCH_FOCUS = bool(check_setting_int(CFG, 'General', 'home_search_focus', HOME_SEARCH_FOCUS))
@ -1042,16 +1069,27 @@ def initialize(console_logging=True):
METADATA_KODI = check_setting_str(CFG, 'General', 'metadata_kodi', '0|0|0|0|0|0|0|0|0|0') METADATA_KODI = check_setting_str(CFG, 'General', 'metadata_kodi', '0|0|0|0|0|0|0|0|0|0')
HOME_LAYOUT = check_setting_str(CFG, 'GUI', 'home_layout', 'poster') HOME_LAYOUT = check_setting_str(CFG, 'GUI', 'home_layout', 'poster')
HISTORY_LAYOUT = check_setting_str(CFG, 'GUI', 'history_layout', 'detailed')
DISPLAY_SHOW_SPECIALS = bool(check_setting_int(CFG, 'GUI', 'display_show_specials', 1))
EPISODE_VIEW_LAYOUT = check_setting_str(CFG, 'GUI', 'episode_view_layout', 'banner')
EPISODE_VIEW_SORT = check_setting_str(CFG, 'GUI', 'episode_view_sort', 'time')
EPISODE_VIEW_DISPLAY_PAUSED = bool(check_setting_int(CFG, 'GUI', 'episode_view_display_paused', 0))
EPISODE_VIEW_MISSED_RANGE = check_setting_int(CFG, 'GUI', 'episode_view_missed_range', 7)
POSTER_SORTBY = check_setting_str(CFG, 'GUI', 'poster_sortby', 'name') POSTER_SORTBY = check_setting_str(CFG, 'GUI', 'poster_sortby', 'name')
POSTER_SORTDIR = check_setting_int(CFG, 'GUI', 'poster_sortdir', 1) POSTER_SORTDIR = check_setting_int(CFG, 'GUI', 'poster_sortdir', 1)
DISPLAY_SHOW_VIEWMODE = check_setting_int(CFG, 'GUI', 'display_show_viewmode', 0)
DISPLAY_SHOW_BACKGROUND = bool(check_setting_int(CFG, 'GUI', 'display_show_background', 0))
DISPLAY_SHOW_BACKGROUND_TRANSLUCENT = bool(check_setting_int(
CFG, 'GUI', 'display_show_background_translucent', 0))
DISPLAY_SHOW_VIEWART = check_setting_int(CFG, 'GUI', 'display_show_viewart', 0)
DISPLAY_SHOW_MINIMUM = bool(check_setting_int(CFG, 'GUI', 'display_show_minimum', 1))
DISPLAY_SHOW_SPECIALS = bool(check_setting_int(CFG, 'GUI', 'display_show_specials', 0))
EPISODE_VIEW_VIEWMODE = check_setting_int(CFG, 'GUI', 'episode_view_viewmode', 0)
EPISODE_VIEW_BACKGROUND = bool(check_setting_int(CFG, 'GUI', 'episode_view_background', 0))
EPISODE_VIEW_BACKGROUND_TRANSLUCENT = bool(check_setting_int(
CFG, 'GUI', 'episode_view_background_translucent', 0))
EPISODE_VIEW_LAYOUT = check_setting_str(CFG, 'GUI', 'episode_view_layout', 'daybyday')
EPISODE_VIEW_SORT = check_setting_str(CFG, 'GUI', 'episode_view_sort', 'time')
EPISODE_VIEW_DISPLAY_PAUSED = bool(check_setting_int(CFG, 'GUI', 'episode_view_display_paused', 1))
EPISODE_VIEW_POSTERS = bool(check_setting_int(CFG, 'GUI', 'episode_view_posters', 1))
EPISODE_VIEW_MISSED_RANGE = check_setting_int(CFG, 'GUI', 'episode_view_missed_range', 7)
HISTORY_LAYOUT = check_setting_str(CFG, 'GUI', 'history_layout', 'detailed')
# initialize NZB and TORRENT providers # initialize NZB and TORRENT providers
providerList = providers.makeProviderList() providerList = providers.makeProviderList()
@ -1134,7 +1172,9 @@ def initialize(console_logging=True):
nzb_prov.enable_backlog = bool(check_setting_int(CFG, prov_id_uc, prov_id + '_enable_backlog', 1)) nzb_prov.enable_backlog = bool(check_setting_int(CFG, prov_id_uc, prov_id + '_enable_backlog', 1))
if not os.path.isfile(CONFIG_FILE): if not os.path.isfile(CONFIG_FILE):
logger.log(u'Unable to find \'' + CONFIG_FILE + '\', all settings will be default!', logger.DEBUG) logger.log(u'Unable to find \'%s\', all settings will be default!' % CONFIG_FILE, logger.DEBUG)
save_config()
elif update_config:
save_config() save_config()
# start up all the threads # start up all the threads
@ -1199,8 +1239,8 @@ def initialize(console_logging=True):
showUpdateScheduler = scheduler.Scheduler( showUpdateScheduler = scheduler.Scheduler(
show_updater.ShowUpdater(), show_updater.ShowUpdater(),
cycleTime=datetime.timedelta(hours=1), cycleTime=datetime.timedelta(hours=1),
threadName='SHOWUPDATER',
start_time=datetime.time(hour=SHOW_UPDATE_HOUR), start_time=datetime.time(hour=SHOW_UPDATE_HOUR),
threadName='SHOWUPDATER',
prevent_cycle_run=showQueueScheduler.action.isShowUpdateRunning) # 3AM prevent_cycle_run=showQueueScheduler.action.isShowUpdateRunning) # 3AM
# searchers # searchers
@ -1213,8 +1253,8 @@ def initialize(console_logging=True):
recentSearchScheduler = scheduler.Scheduler( recentSearchScheduler = scheduler.Scheduler(
search_recent.RecentSearcher(), search_recent.RecentSearcher(),
cycleTime=update_interval, cycleTime=update_interval,
threadName='RECENTSEARCHER',
run_delay=update_now if RECENTSEARCH_STARTUP else datetime.timedelta(minutes=5), run_delay=update_now if RECENTSEARCH_STARTUP else datetime.timedelta(minutes=5),
threadName='RECENTSEARCHER',
prevent_cycle_run=searchQueueScheduler.action.is_recentsearch_in_progress) prevent_cycle_run=searchQueueScheduler.action.is_recentsearch_in_progress)
if [x for x in providers.sortedProviderList() if x.is_active() and if [x for x in providers.sortedProviderList() if x.is_active() and
@ -1235,8 +1275,8 @@ def initialize(console_logging=True):
backlogSearchScheduler = search_backlog.BacklogSearchScheduler( backlogSearchScheduler = search_backlog.BacklogSearchScheduler(
search_backlog.BacklogSearcher(), search_backlog.BacklogSearcher(),
cycleTime=datetime.timedelta(minutes=get_backlog_cycle_time()), cycleTime=datetime.timedelta(minutes=get_backlog_cycle_time()),
threadName='BACKLOG',
run_delay=datetime.timedelta(minutes=backlogdelay), run_delay=datetime.timedelta(minutes=backlogdelay),
threadName='BACKLOG',
prevent_cycle_run=searchQueueScheduler.action.is_standard_backlog_in_progress) prevent_cycle_run=searchQueueScheduler.action.is_standard_backlog_in_progress)
propers_searcher = search_propers.ProperSearcher() propers_searcher = search_propers.ProperSearcher()
@ -1251,9 +1291,9 @@ def initialize(console_logging=True):
properFinderScheduler = scheduler.Scheduler( properFinderScheduler = scheduler.Scheduler(
propers_searcher, propers_searcher,
cycleTime=update_interval, cycleTime=update_interval,
threadName='FINDPROPERS',
start_time=run_at,
run_delay=update_interval, run_delay=update_interval,
start_time=run_at,
threadName='FINDPROPERS',
prevent_cycle_run=searchQueueScheduler.action.is_propersearch_in_progress) prevent_cycle_run=searchQueueScheduler.action.is_propersearch_in_progress)
# processors # processors
@ -1264,10 +1304,8 @@ def initialize(console_logging=True):
silent=not PROCESS_AUTOMATICALLY) silent=not PROCESS_AUTOMATICALLY)
""" """
traktCheckerScheduler = scheduler.Scheduler( traktCheckerScheduler = scheduler.Scheduler(
traktChecker.TraktChecker(), traktChecker.TraktChecker(), cycleTime=datetime.timedelta(hours=1),
cycleTime=datetime.timedelta(hours=1), threadName='TRAKTCHECKER', silent=not USE_TRAKT)
threadName='TRAKTCHECKER',
silent=not USE_TRAKT)
""" """
subtitlesFinderScheduler = scheduler.Scheduler( subtitlesFinderScheduler = scheduler.Scheduler(
subtitles.SubtitlesFinder(), subtitles.SubtitlesFinder(),
@ -1389,17 +1427,17 @@ def save_config():
# For passwords you must include the word `password` in the item_name and # For passwords you must include the word `password` in the item_name and
# add `helpers.encrypt(ITEM_NAME, ENCRYPTION_VERSION)` in save_config() # add `helpers.encrypt(ITEM_NAME, ENCRYPTION_VERSION)` in save_config()
new_config['General'] = {} new_config['General'] = {}
new_config['General']['config_version'] = CONFIG_VERSION
new_config['General']['branch'] = BRANCH new_config['General']['branch'] = BRANCH
new_config['General']['git_remote'] = GIT_REMOTE new_config['General']['git_remote'] = GIT_REMOTE
new_config['General']['cur_commit_hash'] = CUR_COMMIT_HASH new_config['General']['cur_commit_hash'] = CUR_COMMIT_HASH
new_config['General']['cur_commit_branch'] = CUR_COMMIT_BRANCH new_config['General']['cur_commit_branch'] = CUR_COMMIT_BRANCH
new_config['General']['config_version'] = CONFIG_VERSION
new_config['General']['encryption_version'] = int(ENCRYPTION_VERSION) new_config['General']['encryption_version'] = int(ENCRYPTION_VERSION)
new_config['General']['log_dir'] = ACTUAL_LOG_DIR if ACTUAL_LOG_DIR else 'Logs' new_config['General']['log_dir'] = ACTUAL_LOG_DIR if ACTUAL_LOG_DIR else 'Logs'
new_config['General']['file_logging_preset'] = FILE_LOGGING_PRESET if FILE_LOGGING_PRESET else 'DB' new_config['General']['file_logging_preset'] = FILE_LOGGING_PRESET if FILE_LOGGING_PRESET else 'DB'
new_config['General']['socket_timeout'] = SOCKET_TIMEOUT new_config['General']['socket_timeout'] = SOCKET_TIMEOUT
new_config['General']['web_port'] = WEB_PORT
new_config['General']['web_host'] = WEB_HOST new_config['General']['web_host'] = WEB_HOST
new_config['General']['web_port'] = WEB_PORT
new_config['General']['web_ipv6'] = int(WEB_IPV6) new_config['General']['web_ipv6'] = int(WEB_IPV6)
new_config['General']['web_log'] = int(WEB_LOG) new_config['General']['web_log'] = int(WEB_LOG)
new_config['General']['web_root'] = WEB_ROOT new_config['General']['web_root'] = WEB_ROOT
@ -1753,6 +1791,9 @@ def save_config():
new_config['GUI']['gui_name'] = GUI_NAME new_config['GUI']['gui_name'] = GUI_NAME
new_config['GUI']['theme_name'] = THEME_NAME new_config['GUI']['theme_name'] = THEME_NAME
new_config['GUI']['default_home'] = DEFAULT_HOME new_config['GUI']['default_home'] = DEFAULT_HOME
new_config['GUI']['fanart_limit'] = FANART_LIMIT
new_config['GUI']['fanart_panel'] = FANART_PANEL
new_config['GUI']['fanart_ratings'] = '%s' % FANART_RATINGS
new_config['GUI']['use_imdb_info'] = int(USE_IMDB_INFO) new_config['GUI']['use_imdb_info'] = int(USE_IMDB_INFO)
new_config['GUI']['imdb_accounts'] = IMDB_ACCOUNTS new_config['GUI']['imdb_accounts'] = IMDB_ACCOUNTS
new_config['GUI']['fuzzy_dating'] = int(FUZZY_DATING) new_config['GUI']['fuzzy_dating'] = int(FUZZY_DATING)
@ -1765,17 +1806,30 @@ def save_config():
new_config['GUI']['showlist_tagview'] = SHOWLIST_TAGVIEW new_config['GUI']['showlist_tagview'] = SHOWLIST_TAGVIEW
new_config['GUI']['home_layout'] = HOME_LAYOUT new_config['GUI']['home_layout'] = HOME_LAYOUT
new_config['GUI']['history_layout'] = HISTORY_LAYOUT new_config['GUI']['poster_sortby'] = POSTER_SORTBY
new_config['GUI']['poster_sortdir'] = POSTER_SORTDIR
new_config['GUI']['display_show_viewmode'] = int(DISPLAY_SHOW_VIEWMODE)
new_config['GUI']['display_show_background'] = int(DISPLAY_SHOW_BACKGROUND)
new_config['GUI']['display_show_background_translucent'] = int(DISPLAY_SHOW_BACKGROUND_TRANSLUCENT)
new_config['GUI']['display_show_viewart'] = int(DISPLAY_SHOW_VIEWART)
new_config['GUI']['display_show_minimum'] = int(DISPLAY_SHOW_MINIMUM)
new_config['GUI']['display_show_specials'] = int(DISPLAY_SHOW_SPECIALS) new_config['GUI']['display_show_specials'] = int(DISPLAY_SHOW_SPECIALS)
new_config['GUI']['episode_view_viewmode'] = int(EPISODE_VIEW_VIEWMODE)
new_config['GUI']['episode_view_background'] = int(EPISODE_VIEW_BACKGROUND)
new_config['GUI']['episode_view_background_translucent'] = int(EPISODE_VIEW_BACKGROUND_TRANSLUCENT)
new_config['GUI']['episode_view_layout'] = EPISODE_VIEW_LAYOUT new_config['GUI']['episode_view_layout'] = EPISODE_VIEW_LAYOUT
new_config['GUI']['episode_view_sort'] = EPISODE_VIEW_SORT new_config['GUI']['episode_view_sort'] = EPISODE_VIEW_SORT
new_config['GUI']['episode_view_display_paused'] = int(EPISODE_VIEW_DISPLAY_PAUSED) new_config['GUI']['episode_view_display_paused'] = int(EPISODE_VIEW_DISPLAY_PAUSED)
new_config['GUI']['episode_view_posters'] = int(EPISODE_VIEW_POSTERS)
new_config['GUI']['episode_view_missed_range'] = int(EPISODE_VIEW_MISSED_RANGE) new_config['GUI']['episode_view_missed_range'] = int(EPISODE_VIEW_MISSED_RANGE)
new_config['GUI']['poster_sortby'] = POSTER_SORTBY new_config['GUI']['poster_sortby'] = POSTER_SORTBY
new_config['GUI']['poster_sortdir'] = POSTER_SORTDIR new_config['GUI']['poster_sortdir'] = POSTER_SORTDIR
new_config['GUI']['show_tags'] = ','.join(SHOW_TAGS) new_config['GUI']['show_tags'] = ','.join(SHOW_TAGS)
new_config['GUI']['showlist_tagview'] = SHOWLIST_TAGVIEW new_config['GUI']['showlist_tagview'] = SHOWLIST_TAGVIEW
new_config['GUI']['show_tag_default'] = SHOW_TAG_DEFAULT new_config['GUI']['show_tag_default'] = SHOW_TAG_DEFAULT
new_config['GUI']['history_layout'] = HISTORY_LAYOUT
new_config['Subtitles'] = {} new_config['Subtitles'] = {}
new_config['Subtitles']['use_subtitles'] = int(USE_SUBTITLES) new_config['Subtitles']['use_subtitles'] = int(USE_SUBTITLES)

View file

@ -120,6 +120,11 @@ class Quality:
FAILED: 'Failed', FAILED: 'Failed',
SNATCHED_BEST: 'Snatched (Best)'} SNATCHED_BEST: 'Snatched (Best)'}
@staticmethod
def get_quality_css(quality):
return (Quality.qualityStrings[quality].replace('2160p', 'UHD2160p').replace('1080p', 'HD1080p')
.replace('720p', 'HD720p').replace('HD TV', 'HD720p').replace('RawHD TV', 'RawHD'))
@staticmethod @staticmethod
def _getStatusStrings(status): def _getStatusStrings(status):
toReturn = {} toReturn = {}

View file

@ -363,16 +363,14 @@ def make_dirs(path):
parents parents
""" """
logger.log(u"Checking if the path " + path + " already exists", logger.DEBUG)
if not ek.ek(os.path.isdir, path): if not ek.ek(os.path.isdir, path):
# Windows, create all missing folders # Windows, create all missing folders
if os.name == 'nt' or os.name == 'ce': if os.name in ('nt', 'ce'):
try: try:
logger.log(u"Folder " + path + " doesn't exist, creating it", logger.DEBUG) logger.log(u'Path %s doesn\'t exist, creating it' % path, logger.DEBUG)
ek.ek(os.makedirs, path) ek.ek(os.makedirs, path)
except (OSError, IOError) as e: except (OSError, IOError) as e:
logger.log(u"Failed creating " + path + " : " + ex(e), logger.ERROR) logger.log(u'Failed creating %s : %s' % (path, ex(e)), logger.ERROR)
return False return False
# not Windows, create all missing folders and set permissions # not Windows, create all missing folders and set permissions
@ -389,14 +387,14 @@ def make_dirs(path):
continue continue
try: try:
logger.log(u"Folder " + sofar + " doesn't exist, creating it", logger.DEBUG) logger.log(u'Path %s doesn\'t exist, creating it' % sofar, logger.DEBUG)
ek.ek(os.mkdir, sofar) ek.ek(os.mkdir, sofar)
# use normpath to remove end separator, otherwise checks permissions against itself # use normpath to remove end separator, otherwise checks permissions against itself
chmodAsParent(ek.ek(os.path.normpath, sofar)) chmodAsParent(ek.ek(os.path.normpath, sofar))
# do the library update for synoindex # do the library update for synoindex
notifiers.synoindex_notifier.addFolder(sofar) notifiers.synoindex_notifier.addFolder(sofar)
except (OSError, IOError) as e: except (OSError, IOError) as e:
logger.log(u"Failed creating " + sofar + " : " + ex(e), logger.ERROR) logger.log(u'Failed creating %s : %s' % (sofar, ex(e)), logger.ERROR)
return False return False
return True return True
@ -799,6 +797,18 @@ def md5_for_file(filename, block_size=2 ** 16):
return None return None
def md5_for_text(text):
result = None
try:
md5 = hashlib.md5()
md5.update(str(text))
raw_md5 = md5.hexdigest()
result = raw_md5[17:] + raw_md5[9:17] + raw_md5[0:9]
except (StandardError, Exception):
pass
return result
def get_lan_ip(): def get_lan_ip():
""" """
Simple function to get LAN localhost_ip Simple function to get LAN localhost_ip
@ -959,6 +969,7 @@ def validateShow(show, season=None, episode=None):
try: try:
lINDEXER_API_PARMS = sickbeard.indexerApi(show.indexer).api_params.copy() lINDEXER_API_PARMS = sickbeard.indexerApi(show.indexer).api_params.copy()
lINDEXER_API_PARMS['dvdorder'] = 0 != show.dvdorder
if indexer_lang and not indexer_lang == 'en': if indexer_lang and not indexer_lang == 'en':
lINDEXER_API_PARMS['language'] = indexer_lang lINDEXER_API_PARMS['language'] = indexer_lang

View file

@ -16,17 +16,28 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with SickGear. If not, see <http://www.gnu.org/licenses/>. # along with SickGear. If not, see <http://www.gnu.org/licenses/>.
import datetime
import fnmatch
import glob
import os.path import os.path
import re
import shutil
import time
import sickbeard import sickbeard
from sickbeard import helpers, logger, exceptions from sickbeard import helpers, logger, exceptions
from sickbeard import encodingKludge as ek from sickbeard import encodingKludge as ek
from sickbeard import db
from sickbeard.metadata.generic import GenericMetadata from sickbeard.metadata.generic import GenericMetadata
from lib.hachoir_parser import createParser from lib.hachoir_parser import createParser
from lib.hachoir_metadata import extractMetadata from lib.hachoir_metadata import extractMetadata
from lib.send2trash import send2trash
try:
import zlib
except:
pass
class ImageCache: class ImageCache:
@ -36,12 +47,21 @@ class ImageCache:
def __del__(self): def __del__(self):
pass pass
def _cache_dir(self): @staticmethod
def _cache_dir():
""" """
Builds up the full path to the image cache directory Builds up the full path to the image cache directory
""" """
return ek.ek(os.path.abspath, ek.ek(os.path.join, sickbeard.CACHE_DIR, 'images')) return ek.ek(os.path.abspath, ek.ek(os.path.join, sickbeard.CACHE_DIR, 'images'))
def _fanart_dir(self, indexer_id=None):
"""
Builds up the full path to the fanart image cache directory
"""
args = [os.path.join, self._cache_dir(), 'fanart'] + \
(None is not indexer_id and [str(indexer_id).split('.')[0]] or [])
return ek.ek(os.path.abspath, ek.ek(*args))
def _thumbnails_dir(self): def _thumbnails_dir(self):
""" """
Builds up the full path to the thumbnails image cache directory Builds up the full path to the thumbnails image cache directory
@ -56,8 +76,7 @@ class ImageCache:
indexer_id: ID of the show to use in the file name indexer_id: ID of the show to use in the file name
""" """
poster_file_name = str(indexer_id) + '.poster.jpg' return ek.ek(os.path.join, self._cache_dir(), '%s.poster.jpg' % indexer_id)
return ek.ek(os.path.join, self._cache_dir(), poster_file_name)
def banner_path(self, indexer_id): def banner_path(self, indexer_id):
""" """
@ -67,8 +86,17 @@ class ImageCache:
indexer_id: ID of the show to use in the file name indexer_id: ID of the show to use in the file name
""" """
banner_file_name = str(indexer_id) + '.banner.jpg' return ek.ek(os.path.join, self._cache_dir(), '%s.banner.jpg' % indexer_id)
return ek.ek(os.path.join, self._cache_dir(), banner_file_name)
def fanart_path(self, indexer_id):
"""
Builds up the path to a fanart cache for a given Indexer ID
returns: a full path to the cached fanart file for the given Indexer ID
indexer_id: ID of the show to use in the file name
"""
return ek.ek(os.path.join, self._fanart_dir(indexer_id), '%s.fanart.jpg' % indexer_id)
def poster_thumb_path(self, indexer_id): def poster_thumb_path(self, indexer_id):
""" """
@ -78,8 +106,7 @@ class ImageCache:
indexer_id: ID of the show to use in the file name indexer_id: ID of the show to use in the file name
""" """
posterthumb_file_name = str(indexer_id) + '.poster.jpg' return ek.ek(os.path.join, self._thumbnails_dir(), '%s.poster.jpg' % indexer_id)
return ek.ek(os.path.join, self._thumbnails_dir(), posterthumb_file_name)
def banner_thumb_path(self, indexer_id): def banner_thumb_path(self, indexer_id):
""" """
@ -89,58 +116,68 @@ class ImageCache:
indexer_id: ID of the show to use in the file name indexer_id: ID of the show to use in the file name
""" """
bannerthumb_file_name = str(indexer_id) + '.banner.jpg' return ek.ek(os.path.join, self._thumbnails_dir(), '%s.banner.jpg' % indexer_id)
return ek.ek(os.path.join, self._thumbnails_dir(), bannerthumb_file_name)
@staticmethod
def has_file(image_file):
"""
Returns true if a image_file exists
"""
result = []
for filename in ek.ek(glob.glob, image_file):
result.append(ek.ek(os.path.isfile, filename) and filename)
logger.log(u'Found cached %s' % filename, logger.DEBUG)
not any(result) and logger.log(u'No cache for %s' % image_file, logger.DEBUG)
return any(result)
def has_poster(self, indexer_id): def has_poster(self, indexer_id):
""" """
Returns true if a cached poster exists for the given Indexer ID Returns true if a cached poster exists for the given Indexer ID
""" """
poster_path = self.poster_path(indexer_id) return self.has_file(self.poster_path(indexer_id))
logger.log(u"Checking if file " + str(poster_path) + " exists", logger.DEBUG)
return ek.ek(os.path.isfile, poster_path)
def has_banner(self, indexer_id): def has_banner(self, indexer_id):
""" """
Returns true if a cached banner exists for the given Indexer ID Returns true if a cached banner exists for the given Indexer ID
""" """
banner_path = self.banner_path(indexer_id) return self.has_file(self.banner_path(indexer_id))
logger.log(u"Checking if file " + str(banner_path) + " exists", logger.DEBUG)
return ek.ek(os.path.isfile, banner_path) def has_fanart(self, indexer_id):
"""
Returns true if a cached fanart exists for the given Indexer ID
"""
return self.has_file(self.fanart_path(indexer_id))
def has_poster_thumbnail(self, indexer_id): def has_poster_thumbnail(self, indexer_id):
""" """
Returns true if a cached poster thumbnail exists for the given Indexer ID Returns true if a cached poster thumbnail exists for the given Indexer ID
""" """
poster_thumb_path = self.poster_thumb_path(indexer_id) return self.has_file(self.poster_thumb_path(indexer_id))
logger.log(u"Checking if file " + str(poster_thumb_path) + " exists", logger.DEBUG)
return ek.ek(os.path.isfile, poster_thumb_path)
def has_banner_thumbnail(self, indexer_id): def has_banner_thumbnail(self, indexer_id):
""" """
Returns true if a cached banner exists for the given Indexer ID Returns true if a cached banner exists for the given Indexer ID
""" """
banner_thumb_path = self.banner_thumb_path(indexer_id) return self.has_file(self.banner_thumb_path(indexer_id))
logger.log(u"Checking if file " + str(banner_thumb_path) + " exists", logger.DEBUG)
return ek.ek(os.path.isfile, banner_thumb_path)
BANNER = 1 BANNER = 1
POSTER = 2 POSTER = 2
BANNER_THUMB = 3 BANNER_THUMB = 3
POSTER_THUMB = 4 POSTER_THUMB = 4
FANART = 5
def which_type(self, path): def which_type(self, path):
""" """
Analyzes the image provided and attempts to determine whether it is a poster or banner. Analyzes the image provided and attempts to determine whether it is a poster, banner or fanart.
returns: BANNER, POSTER if it concluded one or the other, or None if the image was neither (or didn't exist) returns: BANNER, POSTER, FANART or None if image type is not detected or doesn't exist
path: full path to the image path: full path to the image
""" """
if not ek.ek(os.path.isfile, path): if not ek.ek(os.path.isfile, path):
logger.log(u"Couldn't check the type of " + str(path) + " cause it doesn't exist", logger.WARNING) logger.log(u'File does not exist to determine image type of %s' % path, logger.WARNING)
return None return None
# use hachoir to parse the image for us # use hachoir to parse the image for us
@ -148,66 +185,105 @@ class ImageCache:
img_metadata = extractMetadata(img_parser) img_metadata = extractMetadata(img_parser)
if not img_metadata: if not img_metadata:
logger.log(u"Unable to get metadata from " + str(path) + ", not using your existing image", logger.DEBUG) logger.log(u'Unable to extract metadata from %s, not using existing image' % path, logger.DEBUG)
return None return None
img_ratio = float(img_metadata.get('width')) / float(img_metadata.get('height')) img_ratio = float(img_metadata.get('width')) / float(img_metadata.get('height'))
img_parser.stream._input.close() img_parser.stream._input.close()
msg_success = u'Treating image as %s'\
+ u' with extracted aspect ratio from %s' % path
# most posters are around 0.68 width/height ratio (eg. 680/1000) # most posters are around 0.68 width/height ratio (eg. 680/1000)
if 0.55 < img_ratio < 0.8: if 0.55 < img_ratio < 0.8:
logger.log(msg_success % 'poster', logger.DEBUG)
return self.POSTER return self.POSTER
# most banners are around 5.4 width/height ratio (eg. 758/140) # most banners are around 5.4 width/height ratio (eg. 758/140)
elif 5 < img_ratio < 6: elif 5 < img_ratio < 6:
logger.log(msg_success % 'banner', logger.DEBUG)
return self.BANNER return self.BANNER
# most fanart are around 1.7 width/height ratio (eg. 1280/720 or 1920/1080)
elif 1.7 < img_ratio < 1.8:
if 500 < img_metadata.get('width'):
logger.log(msg_success % 'fanart', logger.DEBUG)
return self.FANART
logger.log(u'Image found with fanart aspect ratio but less than 500 pixels wide, skipped', logger.WARNING)
return None
else: else:
logger.log(u"Image has size ratio of " + str(img_ratio) + ", unknown type", logger.WARNING) logger.log(u'Image not useful with size ratio %s, skipping' % img_ratio, logger.WARNING)
return None return None
def _cache_image_from_file(self, image_path, img_type, indexer_id): def should_refresh(self, image_type=None, provider='local'):
my_db = db.DBConnection('cache.db', row_type='dict')
sql_results = my_db.select('SELECT time FROM lastUpdate WHERE provider = ?',
['imsg_%s_%s' % ((image_type, self.FANART)[None is image_type], provider)])
if sql_results:
minutes_freq = 60 * 3
# daily_freq = 60 * 60 * 23
freq = minutes_freq
now_stamp = int(time.mktime(datetime.datetime.today().timetuple()))
the_time = int(sql_results[0]['time'])
return now_stamp - the_time > freq
return True
def set_last_refresh(self, image_type=None, provider='local'):
my_db = db.DBConnection('cache.db')
my_db.upsert('lastUpdate',
{'time': int(time.mktime(datetime.datetime.today().timetuple()))},
{'provider': 'imsg_%s_%s' % ((image_type, self.FANART)[None is image_type], provider)})
def _cache_image_from_file(self, image_path, img_type, indexer_id, move_file=False):
""" """
Takes the image provided and copies it to the cache folder Takes the image provided and copies or moves it to the cache folder
returns: bool representing success returns: full path to cached file or None
image_path: path to the image we're caching image_path: path to the image to cache
img_type: BANNER or POSTER img_type: BANNER, POSTER, or FANART
indexer_id: id of the show this image belongs to indexer_id: id of the show this image belongs to
move_file: True if action is to move the file else file should be copied
""" """
# generate the path based on the type & indexer_id # generate the path based on the type & indexer_id
fanart_subdir = []
if img_type == self.POSTER: if img_type == self.POSTER:
dest_path = self.poster_path(indexer_id) dest_path = self.poster_path(indexer_id)
elif img_type == self.BANNER: elif img_type == self.BANNER:
dest_path = self.banner_path(indexer_id) dest_path = self.banner_path(indexer_id)
elif img_type == self.FANART:
with open(image_path, mode='rb') as resource:
crc = '%05X' % (zlib.crc32(resource.read()) & 0xFFFFFFFF)
fanart_subdir = [self._fanart_dir(indexer_id)]
dest_path = self.fanart_path(indexer_id).replace('.fanart.jpg', '.%s.fanart.jpg' % crc)
else: else:
logger.log(u"Invalid cache image type: " + str(img_type), logger.ERROR) logger.log(u'Invalid cache image type: ' + str(img_type), logger.ERROR)
return False return False
# make sure the cache folder exists before we try copying to it for cache_dir in [self._cache_dir(), self._thumbnails_dir(), self._fanart_dir()] + fanart_subdir:
if not ek.ek(os.path.isdir, self._cache_dir()): helpers.make_dirs(cache_dir)
logger.log(u"Image cache directory doesn't exist, creating it at " + str(self._cache_dir()))
ek.ek(os.makedirs, self._cache_dir())
if not ek.ek(os.path.isdir, self._thumbnails_dir()): logger.log(u'%sing from %s to %s' % (('Copy', 'Mov')[move_file], image_path, dest_path))
logger.log(u"Thumbnails cache directory doesn't exist, creating it at " + str(self._thumbnails_dir())) if move_file:
ek.ek(os.makedirs, self._thumbnails_dir()) helpers.moveFile(image_path, dest_path)
else:
logger.log(u"Copying from " + image_path + " to " + dest_path)
helpers.copyFile(image_path, dest_path) helpers.copyFile(image_path, dest_path)
return True return ek.ek(os.path.isfile, dest_path) and dest_path or None
def _cache_image_from_indexer(self, show_obj, img_type): def _cache_image_from_indexer(self, show_obj, img_type, num_files=0, max_files=500):
""" """
Retrieves an image of the type specified from indexer and saves it to the cache folder Retrieves an image of the type specified from indexer and saves it to the cache folder
returns: bool representing success returns: bool representing success
show_obj: TVShow object that we want to cache an image for show_obj: TVShow object that we want to cache an image for
img_type: BANNER or POSTER img_type: BANNER, POSTER, or FANART
""" """
# generate the path based on the type & indexer_id # generate the path based on the type & indexer_id
@ -217,6 +293,9 @@ class ImageCache:
elif img_type == self.BANNER: elif img_type == self.BANNER:
img_type_name = 'banner' img_type_name = 'banner'
dest_path = self.banner_path(show_obj.indexerid) dest_path = self.banner_path(show_obj.indexerid)
elif img_type == self.FANART:
img_type_name = 'fanart_all'
dest_path = self.fanart_path(show_obj.indexerid).replace('fanart.jpg', '*')
elif img_type == self.POSTER_THUMB: elif img_type == self.POSTER_THUMB:
img_type_name = 'poster_thumb' img_type_name = 'poster_thumb'
dest_path = self.poster_thumb_path(show_obj.indexerid) dest_path = self.poster_thumb_path(show_obj.indexerid)
@ -224,18 +303,96 @@ class ImageCache:
img_type_name = 'banner_thumb' img_type_name = 'banner_thumb'
dest_path = self.banner_thumb_path(show_obj.indexerid) dest_path = self.banner_thumb_path(show_obj.indexerid)
else: else:
logger.log(u"Invalid cache image type: " + str(img_type), logger.ERROR) logger.log(u'Invalid cache image type: ' + str(img_type), logger.ERROR)
return False return False
# retrieve the image from indexer using the generic metadata class # retrieve the image from indexer using the generic metadata class
#TODO: refactor
metadata_generator = GenericMetadata() metadata_generator = GenericMetadata()
img_data = metadata_generator._retrieve_show_image(img_type_name, show_obj) if img_type == self.FANART:
result = metadata_generator._write_image(img_data, dest_path) image_urls = metadata_generator.retrieve_show_image(img_type_name, show_obj)
if None is image_urls:
return False
crcs = []
for cache_file_name in ek.ek(glob.glob, dest_path):
with open(cache_file_name, mode='rb') as resource:
crc = '%05X' % (zlib.crc32(resource.read()) & 0xFFFFFFFF)
if crc not in crcs:
crcs += [crc]
success = 0
count_urls = len(image_urls)
sources = []
for image_url in image_urls or []:
img_data = helpers.getURL(image_url)
if None is img_data:
continue
crc = '%05X' % (zlib.crc32(img_data) & 0xFFFFFFFF)
if crc in crcs:
count_urls -= 1
continue
crcs += [crc]
img_source = (((('', 'tvdb')['thetvdb.com' in image_url],
'tvrage')['tvrage.com' in image_url],
'fatv')['fanart.tv' in image_url],
'tmdb')['tmdb' in image_url]
img_xtra = ''
if 'tmdb' == img_source:
match = re.search(r'(?:.*\?(\d+$))?', image_url, re.I | re.M)
if match and None is not match.group(1):
img_xtra = match.group(1)
file_desc = '%s.%03d%s.%s' % (
show_obj.indexerid, num_files, ('.%s%s' % (img_source, img_xtra), '')['' == img_source], crc)
cur_file_path = self.fanart_path(file_desc)
result = metadata_generator.write_image(img_data, cur_file_path)
if result and self.FANART != self.which_type(cur_file_path):
try:
ek.ek(os.remove, cur_file_path)
except OSError as e:
logger.log(u'Unable to remove %s: %s / %s' % (cur_file_path, repr(e), str(e)), logger.WARNING)
continue
if img_source:
sources += [img_source]
num_files += (0, 1)[result]
success += (0, 1)[result]
if num_files > max_files:
break
if count_urls:
total = len(ek.ek(glob.glob, dest_path))
logger.log(u'Saved %s of %s fanart images%s. Cached %s of max %s fanart file%s'
% (success, count_urls,
('', ' from ' + ', '.join([x for x in list(set(sources))]))[0 < len(sources)],
total, sickbeard.FANART_LIMIT, helpers.maybe_plural(total)))
return bool(count_urls) and not bool(count_urls - success)
img_data = metadata_generator.retrieve_show_image(img_type_name, show_obj)
if None is img_data:
return False
result = metadata_generator.write_image(img_data, dest_path)
if result:
logger.log(u'Saved image type %s' % img_type_name)
return result return result
def fill_cache(self, show_obj): def clean_fanart(self):
ratings_found = False
fanarts = ek.ek(glob.glob, '%s.jpg' % self._fanart_dir('*'))
if fanarts:
logger.log(u'Reorganising fanart cache files', logger.DEBUG)
for image_path in fanarts:
image_path_parts = ek.ek(os.path.basename, image_path).split('.')
dest_path = self._cache_image_from_file(image_path, self.FANART, '.'.join(image_path_parts[0:-2]), True)
if None is not dest_path:
src_file_id = '.'.join(image_path_parts[1:-2])
rating = sickbeard.FANART_RATINGS.get(image_path_parts[0], {}).get(src_file_id, None)
if None is not rating:
ratings_found = True
dest_file_id = str('.'.join(ek.ek(os.path.basename, dest_path).split('.')[1:-2]))
sickbeard.FANART_RATINGS[image_path_parts[0]][dest_file_id] = rating
del (sickbeard.FANART_RATINGS[image_path_parts[0]][src_file_id])
return ratings_found
def fill_cache(self, show_obj, force=False):
""" """
Caches all images for the given show. Copies them from the show dir if possible, or Caches all images for the given show. Copies them from the show dir if possible, or
downloads them from indexer if they aren't in the show dir. downloads them from indexer if they aren't in the show dir.
@ -243,51 +400,108 @@ class ImageCache:
show_obj: TVShow object to cache images for show_obj: TVShow object to cache images for
""" """
logger.log(u"Checking if we need any cache images for show " + str(show_obj.indexerid), logger.DEBUG) show_id = '%s' % show_obj.indexerid
# check if the images are already cached or not # check if any images are cached
need_images = {self.POSTER: not self.has_poster(show_obj.indexerid), need_images = {self.POSTER: not self.has_poster(show_id),
self.BANNER: not self.has_banner(show_obj.indexerid), self.BANNER: not self.has_banner(show_id),
self.POSTER_THUMB: not self.has_poster_thumbnail(show_obj.indexerid), self.FANART: 0 < sickbeard.FANART_LIMIT and (force or not self.has_fanart(show_id + '.001.*')),
self.BANNER_THUMB: not self.has_banner_thumbnail(show_obj.indexerid)} # use limit? shows less than a limit of say 50 would fail to fulfill images every day
# '.%03d.*' % sickbeard.FANART_LIMIT
self.POSTER_THUMB: not self.has_poster_thumbnail(show_id),
self.BANNER_THUMB: not self.has_banner_thumbnail(show_id)}
if not need_images[self.POSTER] and not need_images[self.BANNER] and not need_images[self.POSTER_THUMB] and not \ if not any(need_images.values()):
need_images[self.BANNER_THUMB]: logger.log(u'%s: No new cache images needed. Done.' % show_id)
logger.log(u"No new cache images needed, not retrieving new ones")
return return
# check the show dir for poster or banner images and use them void = False
if need_images[self.POSTER] or need_images[self.BANNER]: if not void and need_images[self.FANART]:
try: action = ('delete', 'trash')[sickbeard.TRASH_REMOVE_SHOW]
for cur_provider in sickbeard.metadata_provider_dict.values():
logger.log(u"Checking if we can use the show image from the " + cur_provider.name + " metadata",
logger.DEBUG)
if ek.ek(os.path.isfile, cur_provider.get_poster_path(show_obj)):
cur_file_name = os.path.abspath(cur_provider.get_poster_path(show_obj))
cur_file_type = self.which_type(cur_file_name)
if cur_file_type == None: cache_path = self.fanart_path(show_id).replace('%s.fanart.jpg' % show_id, '')
logger.log(u"Unable to retrieve image type, not using the image from " + str(cur_file_name), # num_images = len(fnmatch.filter(os.listdir(cache_path), '*.jpg'))
logger.WARNING)
for cache_dir in ek.ek(glob.glob, cache_path):
if show_id in sickbeard.FANART_RATINGS:
del (sickbeard.FANART_RATINGS[show_id])
logger.log(u'Attempt to %s purge cache file %s' % (action, cache_dir), logger.DEBUG)
try:
if sickbeard.TRASH_REMOVE_SHOW:
send2trash(cache_dir)
else:
shutil.rmtree(cache_dir)
except OSError as e:
logger.log(u'Unable to %s %s: %s / %s' % (action, cache_dir, repr(e), str(e)), logger.WARNING)
try:
checked_files = []
crcs = []
for cur_provider in sickbeard.metadata_provider_dict.values():
# check the show dir for poster or banner images and use them
needed = []
if any([need_images[self.POSTER], need_images[self.BANNER]]):
needed += [[False, cur_provider.get_poster_path(show_obj)]]
if need_images[self.FANART]:
needed += [[True, cur_provider.get_fanart_path(show_obj)]]
if 0 == len(needed):
break
logger.log(u'Checking for images from optional %s metadata' % cur_provider.name, logger.DEBUG)
for all_meta_provs, path_file in needed:
if path_file in checked_files:
continue
checked_files += [path_file]
if ek.ek(os.path.isfile, path_file):
cache_file_name = os.path.abspath(path_file)
with open(cache_file_name, mode='rb') as resource:
crc = '%05X' % (zlib.crc32(resource.read()) & 0xFFFFFFFF)
if crc in crcs:
continue
crcs += [crc]
cur_file_type = self.which_type(cache_file_name)
if None is cur_file_type:
continue continue
logger.log(u"Checking if image " + cur_file_name + " (type " + str( logger.log(u'Checking if image %s (type %s needs metadata: %s)'
cur_file_type) + " needs metadata: " + str(need_images[cur_file_type]), logger.DEBUG) % (cache_file_name, str(cur_file_type),
('No', 'Yes')[True is need_images[cur_file_type]]), logger.DEBUG)
if need_images.get(cur_file_type):
need_images[cur_file_type] = (
(need_images[cur_file_type] + 1, 1)[isinstance(need_images[cur_file_type], bool)],
False)[not all_meta_provs]
if self.FANART == cur_file_type and \
(not sickbeard.FANART_LIMIT or sickbeard.FANART_LIMIT < need_images[cur_file_type]):
continue
logger.log(u'Caching image found in the show directory to the image cache: %s, type %s'
% (cache_file_name, cur_file_type), logger.DEBUG)
self._cache_image_from_file(cache_file_name, cur_file_type, '%s%s' % (
show_id, ('.%03d' % need_images[cur_file_type], '')[
isinstance(need_images[cur_file_type], bool)]))
if cur_file_type in need_images and need_images[cur_file_type]:
logger.log(
u"Found an image in the show directory that doesn't exist in the cache, caching it: " + cur_file_name + ", type " + str(
cur_file_type), logger.DEBUG)
self._cache_image_from_file(cur_file_name, cur_file_type, show_obj.indexerid)
need_images[cur_file_type] = False
except exceptions.ShowDirNotFoundException: except exceptions.ShowDirNotFoundException:
logger.log(u"Unable to search for images in show directory because it doesn't exist", logger.WARNING) logger.log(u'Unable to search for images in show directory because it doesn\'t exist', logger.WARNING)
# download from indexer for missing ones # download missing ones from indexer
for cur_image_type in [self.POSTER, self.BANNER, self.POSTER_THUMB, self.BANNER_THUMB]: for image_type, name_type in [[self.POSTER, 'Poster'], [self.BANNER, 'Banner'], [self.FANART, 'Fanart'],
logger.log(u"Seeing if we still need an image of type " + str(cur_image_type) + ": " + str( [self.POSTER_THUMB, 'Poster Thumb'], [self.BANNER_THUMB, 'Banner Thumb']]:
need_images[cur_image_type]), logger.DEBUG) max_files = (500, sickbeard.FANART_LIMIT)[self.FANART == image_type]
if cur_image_type in need_images and need_images[cur_image_type]: if not max_files or max_files < need_images[image_type]:
self._cache_image_from_indexer(show_obj, cur_image_type) continue
logger.log(u"Done cache check") logger.log(u'Seeing if we still need an image of type %s: %s'
% (name_type, ('No', 'Yes')[True is need_images[image_type]]), logger.DEBUG)
if need_images[image_type]:
file_num = (need_images[image_type] + 1, 1)[isinstance(need_images[image_type], bool)]
if file_num <= max_files:
self._cache_image_from_indexer(show_obj, image_type, file_num, max_files)
logger.log(u'Done cache check')

View file

@ -37,6 +37,7 @@ try:
except ImportError: except ImportError:
pass pass
# ERROR = 40, WARNING = 30, INFO = 20, DEBUG = 10
ERROR = logging.ERROR ERROR = logging.ERROR
WARNING = logging.WARNING WARNING = logging.WARNING
MESSAGE = logging.INFO MESSAGE = logging.INFO
@ -184,6 +185,37 @@ class SBRotatingLogHandler(object):
else: else:
sys.exit(1) sys.exit(1)
@staticmethod
def reverse_readline(filename, buf_size=4096):
"""a generator that returns the lines of a file in reverse order"""
with open(filename) as fh:
segment = None
offset = 0
fh.seek(0, os.SEEK_END)
file_size = remaining_size = fh.tell()
while remaining_size > 0:
offset = min(file_size, offset + buf_size)
fh.seek(file_size - offset)
buf = fh.read(min(remaining_size, buf_size))
remaining_size -= buf_size
lines = buf.split('\n')
# the first line of the buffer is probably not a complete line so
# we'll save it and append it to the last line of the next buffer
# we read
if segment is not None:
# if the previous chunk starts right from the beginning of line
# do not concat the segment to the last line of new chunk
# instead, yield the segment first
if buf[-1] is not '\n':
lines[-1] += segment
else:
yield segment + '\n'
segment = lines[0]
for index in range(len(lines) - 1, 0, -1):
if len(lines[index]):
yield lines[index] + '\n'
yield None is not segment and segment + '\n' or ''
class DispatchingFormatter: class DispatchingFormatter:
def __init__(self, formatters, default_formatter): def __init__(self, formatters, default_formatter):
@ -263,7 +295,10 @@ class TimedCompressedRotatingFileHandler(TimedRotatingFileHandler):
if 0 < self.backupCount: if 0 < self.backupCount:
# find the oldest log file and delete it # find the oldest log file and delete it
all_names = encodingKludge.ek(glob.glob, file_name + '_*') # phase out files named sickbeard.log in favour of sickgear.logs over backup_count days
all_names = encodingKludge.ek(glob.glob, file_name + '_*') + \
encodingKludge.ek(glob.glob, encodingKludge.ek(os.path.join, encodingKludge.ek(
os.path.dirname, file_name), 'sickbeard_*'))
if len(all_names) > self.backupCount: if len(all_names) > self.backupCount:
all_names.sort() all_names.sort()
self.delete_logfile(all_names[0]) self.delete_logfile(all_names[0])

View file

@ -38,9 +38,13 @@ from sickbeard import logger
from sickbeard import encodingKludge as ek from sickbeard import encodingKludge as ek
from sickbeard.exceptions import ex from sickbeard.exceptions import ex
from sickbeard.show_name_helpers import allPossibleShowNames from sickbeard.show_name_helpers import allPossibleShowNames
from sickbeard.indexers import indexer_config
from six import iteritems from six import iteritems
from lib.tmdb_api.tmdb_api import TMDB from lib.tmdb_api.tmdb_api import TMDB
from lib.fanart.core import Request as fanartRequest
import lib.fanart as fanart
class GenericMetadata(): class GenericMetadata():
@ -149,21 +153,21 @@ class GenericMetadata():
def _has_episode_thumb(self, ep_obj): def _has_episode_thumb(self, ep_obj):
location = self.get_episode_thumb_path(ep_obj) location = self.get_episode_thumb_path(ep_obj)
result = location != None and ek.ek(os.path.isfile, location) result = None is not location and ek.ek(os.path.isfile, location)
if location: if location:
logger.log(u"Checking if " + location + " exists: " + str(result), logger.DEBUG) logger.log(u"Checking if " + location + " exists: " + str(result), logger.DEBUG)
return result return result
def _has_season_poster(self, show_obj, season): def _has_season_poster(self, show_obj, season):
location = self.get_season_poster_path(show_obj, season) location = self.get_season_poster_path(show_obj, season)
result = location != None and ek.ek(os.path.isfile, location) result = None is not location and ek.ek(os.path.isfile, location)
if location: if location:
logger.log(u"Checking if " + location + " exists: " + str(result), logger.DEBUG) logger.log(u"Checking if " + location + " exists: " + str(result), logger.DEBUG)
return result return result
def _has_season_banner(self, show_obj, season): def _has_season_banner(self, show_obj, season):
location = self.get_season_banner_path(show_obj, season) location = self.get_season_banner_path(show_obj, season)
result = location != None and ek.ek(os.path.isfile, location) result = None is not location and ek.ek(os.path.isfile, location)
if location: if location:
logger.log(u"Checking if " + location + " exists: " + str(result), logger.DEBUG) logger.log(u"Checking if " + location + " exists: " + str(result), logger.DEBUG)
return result return result
@ -742,30 +746,27 @@ class GenericMetadata():
def _retrieve_show_image(self, image_type, show_obj, which=None): def _retrieve_show_image(self, image_type, show_obj, which=None):
""" """
Gets an image URL from theTVDB.com and TMDB.com, downloads it and returns the data. Gets an image URL from theTVDB.com, fanart.tv and TMDB.com, downloads it and returns the data.
If type is fanart, multiple image src urls are returned instead of a single data image.
image_type: type of image to retrieve (currently supported: fanart, poster, banner) image_type: type of image to retrieve (currently supported: fanart, poster, banner, poster_thumb, banner_thumb)
show_obj: a TVShow object to use when searching for the image show_obj: a TVShow object to use when searching for the image
which: optional, a specific numbered poster to look for which: optional, a specific numbered poster to look for
Returns: the binary image data if available, or else None Returns: the binary image data if available, or else None
""" """
image_url = None
indexer_lang = show_obj.lang indexer_lang = show_obj.lang
try: try:
# There's gotta be a better way of doing this but we don't wanna # There's gotta be a better way of doing this but we don't wanna
# change the language value elsewhere # change the language value elsewhere
lINDEXER_API_PARMS = sickbeard.indexerApi(show_obj.indexer).api_params.copy() lINDEXER_API_PARMS = sickbeard.indexerApi(show_obj.indexer).api_params.copy()
lINDEXER_API_PARMS['banners'] = True lINDEXER_API_PARMS['banners'] = True
lINDEXER_API_PARMS['dvdorder'] = 0 != show_obj.dvdorder
if indexer_lang and not indexer_lang == 'en': if indexer_lang and not 'en' == indexer_lang:
lINDEXER_API_PARMS['language'] = indexer_lang lINDEXER_API_PARMS['language'] = indexer_lang
if show_obj.dvdorder != 0:
lINDEXER_API_PARMS['dvdorder'] = True
t = sickbeard.indexerApi(show_obj.indexer).indexer(**lINDEXER_API_PARMS) t = sickbeard.indexerApi(show_obj.indexer).indexer(**lINDEXER_API_PARMS)
indexer_show_obj = t[show_obj.indexerid] indexer_show_obj = t[show_obj.indexerid]
except (sickbeard.indexer_error, IOError) as e: except (sickbeard.indexer_error, IOError) as e:
@ -773,30 +774,59 @@ class GenericMetadata():
show_obj.indexer).name + ", not downloading images: " + ex(e), logger.ERROR) show_obj.indexer).name + ", not downloading images: " + ex(e), logger.ERROR)
return None return None
if image_type not in ('fanart', 'poster', 'banner', 'poster_thumb', 'banner_thumb'): return_links = False
if 'fanart_all' == image_type:
return_links = True
image_type = 'fanart'
if image_type not in ('poster', 'banner', 'fanart', 'poster_thumb', 'banner_thumb'):
logger.log(u"Invalid image type " + str(image_type) + ", couldn't find it in the " + sickbeard.indexerApi( logger.log(u"Invalid image type " + str(image_type) + ", couldn't find it in the " + sickbeard.indexerApi(
show_obj.indexer).name + " object", logger.ERROR) show_obj.indexer).name + " object", logger.ERROR)
return None return None
if image_type == 'poster_thumb': image_urls = []
init_url = None
if 'poster_thumb' == image_type:
if getattr(indexer_show_obj, 'poster', None) is not None: if getattr(indexer_show_obj, 'poster', None) is not None:
image_url = re.sub('posters', '_cache/posters', indexer_show_obj['poster']) image_url = re.sub('posters', '_cache/posters', indexer_show_obj['poster'])
elif image_type == 'banner_thumb': if image_url:
image_urls.append(image_url)
for item in self._fanart_urls_from_show(show_obj, image_type, indexer_lang, True) or []:
image_urls.append(item[2])
if 0 == len(image_urls):
for item in self._tmdb_image_url(show_obj, image_type) or []:
image_urls.append(item[2])
elif 'banner_thumb' == image_type:
if getattr(indexer_show_obj, 'banner', None) is not None: if getattr(indexer_show_obj, 'banner', None) is not None:
image_url = re.sub('graphical', '_cache/graphical', indexer_show_obj['banner']) image_url = re.sub('graphical', '_cache/graphical', indexer_show_obj['banner'])
if image_url:
image_urls.append(image_url)
for item in self._fanart_urls_from_show(show_obj, image_type, indexer_lang, True) or []:
image_urls.append(item[2])
else: else:
for item in self._fanart_urls_from_show(show_obj, image_type, indexer_lang) or []:
image_urls.append(item[2])
if getattr(indexer_show_obj, image_type, None) is not None: if getattr(indexer_show_obj, image_type, None) is not None:
image_url = indexer_show_obj[image_type] image_url = indexer_show_obj[image_type]
# Try and get posters and fanart from TMDB
if image_url is None:
if image_type in ('poster', 'poster_thumb'):
image_url = self._retrieve_show_images_from_tmdb(show_obj, poster=True)
elif image_type == 'fanart':
image_url = self._retrieve_show_images_from_tmdb(show_obj, backdrop=True)
if image_url: if image_url:
image_data = metadata_helpers.getShowImage(image_url, which) image_urls.append(image_url)
if 'poster' == image_type:
init_url = image_url
if 0 == len(image_urls) or 'fanart' == image_type:
for item in self._tmdb_image_url(show_obj, image_type) or []:
image_urls.append('%s?%s' % (item[2], item[0]))
image_data = len(image_urls) or None
if image_data:
if return_links:
return image_urls
else:
image_data = metadata_helpers.getShowImage((init_url, image_urls[0])[None is init_url], which)
if None is not image_data:
return image_data return image_data
return None return None
@ -818,15 +848,12 @@ class GenericMetadata():
# There's gotta be a better way of doing this but we don't wanna # There's gotta be a better way of doing this but we don't wanna
# change the language value elsewhere # change the language value elsewhere
lINDEXER_API_PARMS = sickbeard.indexerApi(show_obj.indexer).api_params.copy() lINDEXER_API_PARMS = sickbeard.indexerApi(show_obj.indexer).api_params.copy()
lINDEXER_API_PARMS['banners'] = True lINDEXER_API_PARMS['banners'] = True
lINDEXER_API_PARMS['dvdorder'] = 0 != show_obj.dvdorder
if indexer_lang and not indexer_lang == 'en': if indexer_lang and not indexer_lang == 'en':
lINDEXER_API_PARMS['language'] = indexer_lang lINDEXER_API_PARMS['language'] = indexer_lang
if show_obj.dvdorder != 0:
lINDEXER_API_PARMS['dvdorder'] = True
t = sickbeard.indexerApi(show_obj.indexer).indexer(**lINDEXER_API_PARMS) t = sickbeard.indexerApi(show_obj.indexer).indexer(**lINDEXER_API_PARMS)
indexer_show_obj = t[show_obj.indexerid] indexer_show_obj = t[show_obj.indexerid]
except (sickbeard.indexer_error, IOError) as e: except (sickbeard.indexer_error, IOError) as e:
@ -874,8 +901,8 @@ class GenericMetadata():
# There's gotta be a better way of doing this but we don't wanna # There's gotta be a better way of doing this but we don't wanna
# change the language value elsewhere # change the language value elsewhere
lINDEXER_API_PARMS = sickbeard.indexerApi(show_obj.indexer).api_params.copy() lINDEXER_API_PARMS = sickbeard.indexerApi(show_obj.indexer).api_params.copy()
lINDEXER_API_PARMS['banners'] = True lINDEXER_API_PARMS['banners'] = True
lINDEXER_API_PARMS['dvdorder'] = 0 != show_obj.dvdorder
if indexer_lang and not indexer_lang == 'en': if indexer_lang and not indexer_lang == 'en':
lINDEXER_API_PARMS['language'] = indexer_lang lINDEXER_API_PARMS['language'] = indexer_lang
@ -950,10 +977,10 @@ class GenericMetadata():
except: except:
indexer = None indexer = None
if showXML.findtext('tvdbid') != None: if None is not showXML.findtext('tvdbid'):
indexer_id = int(showXML.findtext('tvdbid')) indexer_id = int(showXML.findtext('tvdbid'))
indexer = INDEXER_TVDB indexer = INDEXER_TVDB
elif showXML.findtext('id') != None: elif None is not showXML.findtext('id'):
indexer_id = int(showXML.findtext('id')) indexer_id = int(showXML.findtext('id'))
try: try:
indexer = INDEXER_TVDB if [s for s in showXML.findall('.//*') if s.text and s.text.find('thetvdb.com') != -1] else indexer indexer = INDEXER_TVDB if [s for s in showXML.findall('.//*') if s.text and s.text.find('thetvdb.com') != -1] else indexer
@ -975,7 +1002,15 @@ class GenericMetadata():
return (indexer_id, name, indexer) return (indexer_id, name, indexer)
def _retrieve_show_images_from_tmdb(self, show, backdrop=False, poster=False): @staticmethod
def _tmdb_image_url(show, image_type):
types = {'poster': 'poster_path',
'banner': None,
'fanart': 'backdrop_path',
'fanart_all': 'backdrops',
'poster_thumb': 'poster_path',
'banner_thumb': None}
# get TMDB configuration info # get TMDB configuration info
tmdb = TMDB(sickbeard.TMDB_API_KEY) tmdb = TMDB(sickbeard.TMDB_API_KEY)
config = tmdb.Configuration() config = tmdb.Configuration()
@ -984,21 +1019,90 @@ class GenericMetadata():
sizes = response['images']['poster_sizes'] sizes = response['images']['poster_sizes']
def size_str_to_int(x): def size_str_to_int(x):
return float("inf") if x == 'original' else int(x[1:]) return float('inf') if x == 'original' else int(x[1:])
max_size = max(sizes, key=size_str_to_int) max_size = max(sizes, key=size_str_to_int)
try: try:
search = tmdb.Search() itemlist = []
for show_name in set(allPossibleShowNames(show)): for (src, name) in [(indexer_config.INDEXER_TVDB, 'tvdb'), (indexer_config.INDEXER_IMDB, 'imdb'),
for result in search.collection({'query': show_name})['results'] + search.tv({'query': show_name})[ (indexer_config.INDEXER_TVRAGE, 'tvrage')]:
'results']: is_id = show.ids.get(src, {}).get('id', None)
if backdrop and result['backdrop_path']: if not is_id:
return "{0}{1}{2}".format(base_url, max_size, result['backdrop_path']) continue
elif poster and result['poster_path']:
return "{0}{1}{2}".format(base_url, max_size, result['poster_path'])
except Exception as e: result = tmdb.Find(is_id).info({'external_source': '%s_id' % name})
if 'tv_results' not in result or not len(result['tv_results']):
continue
tmdb_show = result['tv_results'][0]
if 'fanart' == image_type:
tv_obj = tmdb.TV(tmdb_show['id'])
rjson_info = tv_obj.info({'append_to_response': 'images', 'include_image_language': 'en,null'})
rjson_img = rjson_info['images']
for art in rjson_img[types['fanart_all']] or []:
if 'vote_average' not in art or 'file_path' not in art:
continue
art_likes = art['vote_average']
url = u'%s%s%s' % (base_url, max_size, art['file_path'])
itemlist += [[tmdb_show['id'], art_likes, url]]
itemlist.sort(lambda a, b: cmp((a[1]), (b[1])), reverse=True)
return itemlist
elif tmdb_show[types[image_type]]:
return [[tmdb_show['id'], tmdb_show['vote_average'], '%s%s%s' % (base_url, max_size, tmdb_show[types[image_type]])]]
except (StandardError, Exception):
pass pass
logger.log(u"Could not find any posters or background for " + show.name, logger.DEBUG) logger.log(u'Could not find any %s images on TMDB for %s' % (image_type, show.name), logger.DEBUG)
def _fanart_urls_from_show(self, show, image_type='banner', lang='en', thumb=False):
try:
tvdb_id = show.ids.get(indexer_config.INDEXER_TVDB, {}).get('id', None)
if tvdb_id:
return self._fanart_urls(tvdb_id, image_type, lang, thumb)
except (StandardError, Exception):
pass
logger.log(u'Could not find any %s images on Fanart.tv for %s' % (image_type, show.name), logger.DEBUG)
@staticmethod
def _fanart_urls(tvdb_id, image_type='banner', lang='en', thumb=False):
types = {'poster': fanart.TYPE.TV.POSTER,
'banner': fanart.TYPE.TV.BANNER,
'fanart': fanart.TYPE.TV.BACKGROUND,
'poster_thumb': fanart.TYPE.TV.POSTER,
'banner_thumb': fanart.TYPE.TV.BANNER}
try:
if tvdb_id:
request = fanartRequest(apikey=sickbeard.FANART_API_KEY, tvdb_id=tvdb_id)
resp = request.response()
itemlist = []
for art in resp[types[image_type]]:
if ('url' in art and 10 > len(art['url']))\
or ('lang' in art and lang != art['lang']):
continue
try:
art_id = int(art['id'])
art_likes = int(art['likes'])
url = (art['url'], re.sub('/fanart/', '/preview/', art['url']))[thumb]
except:
continue
itemlist += [[art_id, art_likes, url]]
itemlist.sort(lambda a, b: cmp((a[1], a[0]), (b[1], b[0])), reverse=True)
return itemlist
except Exception as e:
raise
def retrieve_show_image(self, image_type, show_obj, which=None):
return self._retrieve_show_image(image_type=image_type, show_obj=show_obj, which=which)
def write_image(self, image_data, image_path):
return self._write_image(image_data=image_data, image_path=image_path)

View file

@ -21,22 +21,18 @@ from sickbeard import logger
def getShowImage(url, imgNum=None): def getShowImage(url, imgNum=None):
image_data = None # @UnusedVariable
if url == None: if None is url:
return None return None
# if they provided a fanart number try to use it instead # if they provided a fanart number try to use it instead
if imgNum != None: temp_url = url if None is imgNum else url.split('-')[0] + '-' + str(imgNum) + '.jpg'
tempURL = url.split('-')[0] + "-" + str(imgNum) + ".jpg"
else:
tempURL = url
logger.log(u"Fetching image from " + tempURL, logger.DEBUG) logger.log(u'Fetching image from ' + temp_url, logger.DEBUG)
image_data = helpers.getURL(tempURL) image_data = helpers.getURL(temp_url)
if image_data is None: if None is image_data:
logger.log(u"There was an error trying to retrieve the image, aborting", logger.ERROR) logger.log(u'There was an error trying to retrieve the image, aborting', logger.ERROR)
return return
return image_data return image_data

View file

@ -403,7 +403,7 @@ class GenericProvider:
'udp://tracker.internetwarriors.net:1337', 'udp://tracker.internetwarriors.net:1337/announce', 'udp://tracker.internetwarriors.net:1337', 'udp://tracker.internetwarriors.net:1337/announce',
'udp://tracker.leechers-paradise.org:6969', 'udp://tracker.leechers-paradise.org:6969/announce', 'udp://tracker.leechers-paradise.org:6969', 'udp://tracker.leechers-paradise.org:6969/announce',
'udp://tracker.opentrackr.org:1337/announce', 'udp://tracker.torrent.eu.org:451/announce', 'udp://tracker.opentrackr.org:1337/announce', 'udp://tracker.torrent.eu.org:451/announce',
'udp://tracker.trackerfix.com:80/announce'])) or None) 'udp://tracker.trackerfix.com:80/announce', 'udp://tracker.zer0day.to:1337/announce'])) or None)
def get_show(self, item, **kwargs): def get_show(self, item, **kwargs):
return None return None

View file

@ -138,7 +138,7 @@ class ShowQueue(generic_queue.GenericQueue):
return queueItemObj return queueItemObj
def refreshShow(self, show, force=False, scheduled_update=False, after_update=False, def refreshShow(self, show, force=False, scheduled_update=False, after_update=False,
priority=generic_queue.QueuePriorities.HIGH, **kwargs): priority=generic_queue.QueuePriorities.HIGH, force_image_cache=False, **kwargs):
if self.isBeingRefreshed(show) and not force: if self.isBeingRefreshed(show) and not force:
raise exceptions.CantRefreshException('This show is already being refreshed, not refreshing again.') raise exceptions.CantRefreshException('This show is already being refreshed, not refreshing again.')
@ -149,7 +149,8 @@ class ShowQueue(generic_queue.GenericQueue):
logger.DEBUG) logger.DEBUG)
return return
queueItemObj = QueueItemRefresh(show, force=force, scheduled_update=scheduled_update, priority=priority, **kwargs) queueItemObj = QueueItemRefresh(show, force=force, scheduled_update=scheduled_update, priority=priority,
force_image_cache=force_image_cache, **kwargs)
self.add_item(queueItemObj) self.add_item(queueItemObj)
@ -487,7 +488,8 @@ class QueueItemAdd(ShowQueueItem):
class QueueItemRefresh(ShowQueueItem): class QueueItemRefresh(ShowQueueItem):
def __init__(self, show=None, force=False, scheduled_update=False, priority=generic_queue.QueuePriorities.HIGH, **kwargs): def __init__(self, show=None, force=False, scheduled_update=False, priority=generic_queue.QueuePriorities.HIGH,
force_image_cache=False, **kwargs):
ShowQueueItem.__init__(self, ShowQueueActions.REFRESH, show, scheduled_update) ShowQueueItem.__init__(self, ShowQueueActions.REFRESH, show, scheduled_update)
# do refreshes first because they're quick # do refreshes first because they're quick
@ -496,6 +498,8 @@ class QueueItemRefresh(ShowQueueItem):
# force refresh certain items # force refresh certain items
self.force = force self.force = force
self.force_image_cache = force_image_cache
self.kwargs = kwargs self.kwargs = kwargs
def run(self): def run(self):
@ -507,7 +511,7 @@ class QueueItemRefresh(ShowQueueItem):
self.show.writeMetadata() self.show.writeMetadata()
#if self.force: #if self.force:
# self.show.updateMetadata() # self.show.updateMetadata()
self.show.populateCache() self.show.populateCache(self.force_image_cache)
# Load XEM data to DB for show # Load XEM data to DB for show
if self.show.indexerid in sickbeard.scene_exceptions.xem_ids_list[self.show.indexer]: if self.show.indexerid in sickbeard.scene_exceptions.xem_ids_list[self.show.indexer]:
@ -652,7 +656,7 @@ class QueueItemUpdate(ShowQueueItem):
if self.priority != generic_queue.QueuePriorities.NORMAL: if self.priority != generic_queue.QueuePriorities.NORMAL:
self.kwargs['priority'] = self.priority self.kwargs['priority'] = self.priority
sickbeard.showQueueScheduler.action.refreshShow(self.show, self.force, self.scheduled_update, after_update=True, sickbeard.showQueueScheduler.action.refreshShow(self.show, self.force, self.scheduled_update, after_update=True,
**self.kwargs) force_image_cache=self.force_web, **self.kwargs)
class QueueItemForceUpdate(QueueItemUpdate): class QueueItemForceUpdate(QueueItemUpdate):

View file

@ -17,18 +17,10 @@
# along with SickGear. If not, see <http://www.gnu.org/licenses/>. # along with SickGear. If not, see <http://www.gnu.org/licenses/>.
import datetime import datetime
import os
import sickbeard import sickbeard
from sickbeard import logger, exceptions, ui, db, network_timezones, failed_history
from sickbeard import logger
from sickbeard import exceptions
from sickbeard import ui
from sickbeard.exceptions import ex from sickbeard.exceptions import ex
from sickbeard import encodingKludge as ek
from sickbeard import db
from sickbeard import network_timezones
from sickbeard import failed_history
class ShowUpdater: class ShowUpdater:
@ -109,7 +101,7 @@ class ShowUpdater:
logger.log( logger.log(
u'Not updating episodes for show ' + curShow.name + ' because it\'s marked as ended and ' + u'Not updating episodes for show ' + curShow.name + ' because it\'s marked as ended and ' +
'last/next episode is not within the grace period.', logger.DEBUG) 'last/next episode is not within the grace period.', logger.DEBUG)
cur_queue_item = sickbeard.showQueueScheduler.action.refreshShow(curShow, True, True) cur_queue_item = sickbeard.showQueueScheduler.action.refreshShow(curShow, True, True, force_image_cache=True)
pi_list.append(cur_queue_item) pi_list.append(cur_queue_item)

View file

@ -60,7 +60,7 @@ from sickbeard import encodingKludge as ek
from common import Quality, Overview, statusStrings from common import Quality, Overview, statusStrings
from common import DOWNLOADED, SNATCHED, SNATCHED_PROPER, SNATCHED_BEST, ARCHIVED, IGNORED, UNAIRED, WANTED, SKIPPED, \ from common import DOWNLOADED, SNATCHED, SNATCHED_PROPER, SNATCHED_BEST, ARCHIVED, IGNORED, UNAIRED, WANTED, SKIPPED, \
UNKNOWN, FAILED UNKNOWN, FAILED, SUBTITLED
from common import NAMING_DUPLICATE, NAMING_EXTEND, NAMING_LIMITED_EXTEND, NAMING_SEPARATED_REPEAT, \ from common import NAMING_DUPLICATE, NAMING_EXTEND, NAMING_LIMITED_EXTEND, NAMING_SEPARATED_REPEAT, \
NAMING_LIMITED_EXTEND_E_PREFIXED NAMING_LIMITED_EXTEND_E_PREFIXED
@ -503,12 +503,10 @@ class TVShow(object):
t = sickbeard.indexerApi(self.indexer).indexer(**lINDEXER_API_PARMS) t = sickbeard.indexerApi(self.indexer).indexer(**lINDEXER_API_PARMS)
cachedShow = t[self.indexerid] cachedShow = t[self.indexerid]
cachedSeasons = {}
if None is cachedShow: if None is cachedShow:
logger.log('No cache showdata to parse from %s' % sickbeard.indexerApi(self.indexer).name)
return scannedEps return scannedEps
cachedSeasons = {}
for curResult in sqlResults: for curResult in sqlResults:
deleteEp = False deleteEp = False
@ -1072,19 +1070,26 @@ class TVShow(object):
sickbeard.showList = [x for x in sickbeard.showList if int(x.indexerid) != self.indexerid] sickbeard.showList = [x for x in sickbeard.showList if int(x.indexerid) != self.indexerid]
# clear the cache # clear the cache
image_cache_dir = ek.ek(os.path.join, sickbeard.CACHE_DIR, 'images') ic = image_cache.ImageCache()
for path, dirs, files in ek.ek(os.walk, image_cache_dir): for cache_obj in ek.ek(glob.glob, ic.poster_path(self.indexerid).replace('poster.jpg', '*')) \
for filename in ek.ek(fnmatch.filter, files, '%s.*' % self.indexerid): + ek.ek(glob.glob, ic.poster_thumb_path(self.indexerid).replace('poster.jpg', '*')) \
cache_file = ek.ek(os.path.join, path, filename) + ek.ek(glob.glob, ic.fanart_path(self.indexerid).replace('%s.fanart.jpg' % self.indexerid, '')):
logger.log('Attempt to %s cache file %s' % (action, cache_file)) cache_dir = ek.ek(os.path.isdir, cache_obj)
logger.log('Attempt to %s cache %s %s' % (action, cache_dir and 'dir' or 'file', cache_obj))
try: try:
if sickbeard.TRASH_REMOVE_SHOW: if sickbeard.TRASH_REMOVE_SHOW:
ek.ek(send2trash, cache_file) ek.ek(send2trash, cache_obj)
elif cache_dir:
ek.ek(shutil.rmtree, cache_obj)
else: else:
ek.ek(os.remove, cache_file) ek.ek(os.remove, cache_obj)
except OSError as e: except OSError as e:
logger.log('Unable to %s %s: %s / %s' % (action, cache_file, repr(e), str(e)), logger.WARNING) logger.log('Unable to %s %s: %s / %s' % (action, cache_obj, repr(e), str(e)), logger.WARNING)
show_id = '%s' % self.indexerid
if show_id in sickbeard.FANART_RATINGS:
del sickbeard.FANART_RATINGS[show_id]
# remove entire show folder # remove entire show folder
if full: if full:
@ -1092,7 +1097,7 @@ class TVShow(object):
logger.log('Attempt to %s show folder %s' % (action, self._location)) logger.log('Attempt to %s show folder %s' % (action, self._location))
# check first the read-only attribute # check first the read-only attribute
file_attribute = ek.ek(os.stat, self.location)[0] file_attribute = ek.ek(os.stat, self.location)[0]
if (not file_attribute & stat.S_IWRITE): if not file_attribute & stat.S_IWRITE:
# File is read-only, so make it writeable # File is read-only, so make it writeable
logger.log('Attempting to make writeable the read only folder %s' % self._location, logger.DEBUG) logger.log('Attempting to make writeable the read only folder %s' % self._location, logger.DEBUG)
try: try:
@ -1114,11 +1119,11 @@ class TVShow(object):
except OSError as e: except OSError as e:
logger.log('Unable to %s %s: %s / %s' % (action, self._location, repr(e), str(e)), logger.WARNING) logger.log('Unable to %s %s: %s / %s' % (action, self._location, repr(e), str(e)), logger.WARNING)
def populateCache(self): def populateCache(self, force=False):
cache_inst = image_cache.ImageCache() cache_inst = image_cache.ImageCache()
logger.log('Checking & filling cache for show %s' % self.name) logger.log('Checking & filling cache for show %s' % self.name)
cache_inst.fill_cache(self) cache_inst.fill_cache(self, force)
def refreshDir(self): def refreshDir(self):
@ -1233,7 +1238,23 @@ class TVShow(object):
try: try:
helpers.moveFile(cache_file, new_cachefile) helpers.moveFile(cache_file, new_cachefile)
except Exception as e: except Exception as e:
logger.log('Unable to rename %s to %s: %s / %s' % (cache_file, new_cachefile, repr(e), str(e)), logger.WARNING) logger.log('Unable to rename %s to %s: %s / %s' % (cache_file, new_cachefile, repr(e), str(e)),
logger.WARNING)
ic = image_cache.ImageCache()
cache_dir = ic.fanart_path(old_indexerid).replace('%s.fanart.jpg' % old_indexerid, '').rstrip('\/')
new_cache_dir = ic.fanart_path(self.indexerid).replace('%s.fanart.jpg' % self.indexerid, '').rstrip('\/')
try:
helpers.moveFile(cache_dir, new_cache_dir)
except Exception as e:
logger.log('Unable to rename %s to %s: %s / %s' % (cache_dir, new_cache_dir, repr(e), str(e)),
logger.WARNING)
rating = sickbeard.FANART_RATINGS.get('%s' % old_indexerid)
if rating:
del sickbeard.FANART_RATINGS['%s' % old_indexerid]
sickbeard.FANART_RATINGS['%s' % self.indexerid] = rating
sickbeard.save_config()
name_cache.buildNameCache(self) name_cache.buildNameCache(self)
@ -1294,27 +1315,21 @@ class TVShow(object):
myDB.upsert('imdb_info', newValueDict, controlValueDict) myDB.upsert('imdb_info', newValueDict, controlValueDict)
def __str__(self): def __str__(self):
toReturn = '' return 'indexerid: %s\n' % self.indexerid \
toReturn += 'indexerid: %s\n' % self.indexerid + 'indexer: %s\n' % self.indexerid \
toReturn += 'indexer: %s\n' % self.indexer + 'name: %s\n' % self.name \
toReturn += 'name: %s\n' % self.name + 'location: %s\n' % self._location \
toReturn += 'location: %s\n' % self._location + ('', 'network: %s\n' % self.network)[self.network] \
if self.network: + ('', 'airs: %s\n' % self.airs)[self.airs] \
toReturn += 'network: %s\n' % self.network + ('', 'status: %s\n' % self.status)[self.status] \
if self.airs: + 'startyear: %s\n' % self.startyear \
toReturn += 'airs: %s\n' % self.airs + ('', 'genre: %s\n' % self.genre)[self.genre] \
if self.status: + 'classification: %s\n' % self.classification \
toReturn += 'status: %s\n' % self.status + 'runtime: %s\n' % self.runtime \
toReturn += 'startyear: %s\n' % self.startyear + 'quality: %s\n' % self.quality \
if self.genre: + 'scene: %s\n' % self.is_scene \
toReturn += 'genre: %s\n' % self.genre + 'sports: %s\n' % self.is_sports \
toReturn += 'classification: %s\n' % self.classification + 'anime: %s\n' % self.is_anime
toReturn += 'runtime: %s\n' % self.runtime
toReturn += 'quality: %s\n' % self.quality
toReturn += 'scene: %s\n' % self.is_scene
toReturn += 'sports: %s\n' % self.is_sports
toReturn += 'anime: %s\n' % self.is_anime
return toReturn
def wantEpisode(self, season, episode, quality, manualSearch=False): def wantEpisode(self, season, episode, quality, manualSearch=False):
@ -1398,7 +1413,7 @@ class TVShow(object):
return Overview.SKIPPED return Overview.SKIPPED
if status in (UNAIRED, UNKNOWN): if status in (UNAIRED, UNKNOWN):
return Overview.UNAIRED return Overview.UNAIRED
if status in Quality.DOWNLOADED + Quality.SNATCHED + Quality.SNATCHED_PROPER + Quality.FAILED + Quality.SNATCHED_BEST: if status in [SUBTITLED] + Quality.DOWNLOADED + Quality.SNATCHED + Quality.SNATCHED_PROPER + Quality.FAILED + Quality.SNATCHED_BEST:
if FAILED == status: if FAILED == status:
return Overview.WANTED return Overview.WANTED
@ -1493,7 +1508,8 @@ class TVEpisode(object):
release_group = property(lambda self: self._release_group, dirty_setter('_release_group')) release_group = property(lambda self: self._release_group, dirty_setter('_release_group'))
def _set_location(self, new_location): def _set_location(self, new_location):
logger.log('Setter sets location to %s' % new_location, logger.DEBUG) log_vals = (('clears', ''), ('sets', ' to ' + new_location))[any(new_location)]
logger.log(u'Setter %s location%s' % log_vals, logger.DEBUG)
# self._location = newLocation # self._location = newLocation
dirty_setter('_location')(self, new_location) dirty_setter('_location')(self, new_location)
@ -1981,18 +1997,16 @@ class TVEpisode(object):
def __str__(self): def __str__(self):
toReturn = '' return '%s - %sx%s - %s\n' % (self.show.name, self.season, self.episode, self.name) \
toReturn += '%s - %sx%s - %s\n' % (self.show.name, self.season, self.episode, self.name) + 'location: %s\n' % self.location \
toReturn += 'location: %s\n' % self.location + 'description: %s\n' % self.description \
toReturn += 'description: %s\n' % self.description + 'subtitles: %s\n' % ','.join(self.subtitles) \
toReturn += 'subtitles: %s\n' % ','.join(self.subtitles) + 'subtitles_searchcount: %s\n' % self.subtitles_searchcount \
toReturn += 'subtitles_searchcount: %s\n' % self.subtitles_searchcount + 'subtitles_lastsearch: %s\n' % self.subtitles_lastsearch \
toReturn += 'subtitles_lastsearch: %s\n' % self.subtitles_lastsearch + 'airdate: %s (%s)\n' % (self.airdate.toordinal(), self.airdate) \
toReturn += 'airdate: %s (%s)\n' % (self.airdate.toordinal(), self.airdate) + 'hasnfo: %s\n' % self.hasnfo \
toReturn += 'hasnfo: %s\n' % self.hasnfo + 'hastbn: %s\n' % self.hastbn \
toReturn += 'hastbn: %s\n' % self.hastbn + 'status: %s\n' % self.status
toReturn += 'status: %s\n' % self.status
return toReturn
def createMetaFiles(self): def createMetaFiles(self):
@ -2067,7 +2081,7 @@ class TVEpisode(object):
'(SELECT scene_episode FROM tv_episodes WHERE indexer = ? AND showid = ? AND season = ? AND episode = ?));', '(SELECT scene_episode FROM tv_episodes WHERE indexer = ? AND showid = ? AND season = ? AND episode = ?));',
[self.show.indexer, self.show.indexerid, self.season, self.episode, self.indexerid, self.indexer, self.name, [self.show.indexer, self.show.indexerid, self.season, self.episode, self.indexerid, self.indexer, self.name,
self.description, self.description,
",".join([sub for sub in self.subtitles]), self.subtitles_searchcount, self.subtitles_lastsearch, ','.join([sub for sub in self.subtitles]), self.subtitles_searchcount, self.subtitles_lastsearch,
self.airdate.toordinal(), self.hasnfo, self.hastbn, self.status, self.location, self.file_size, self.airdate.toordinal(), self.hasnfo, self.hastbn, self.status, self.location, self.file_size,
self.release_name, self.is_proper, self.show.indexerid, self.season, self.episode, self.release_name, self.is_proper, self.show.indexerid, self.season, self.episode,
self.absolute_number, self.version, self.release_group, self.absolute_number, self.version, self.release_group,

View file

@ -1235,24 +1235,21 @@ class CMD_Logs(ApiCall):
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, handler, args, kwargs)
def run(self): def run(self):
""" view sickbeard's log """ """ view sickgear's log """
# 10 = Debug / 20 = Info / 30 = Warning / 40 = Error # 10 = Debug / 20 = Info / 30 = Warning / 40 = Error
minLevel = logger.reverseNames[str(self.min_level).upper()] min_level = logger.reverseNames[str(self.min_level).upper()]
max_lines = 50
data = []
if os.path.isfile(logger.sb_log_instance.log_file_path):
with ek.ek(open, logger.sb_log_instance.log_file_path) as f:
data = f.readlines()
regex = "^(\d\d\d\d)\-(\d\d)\-(\d\d)\s*(\d\d)\:(\d\d):(\d\d)\s*([A-Z]+)\s*(.+?)\s*\:\:\s*(.*)$" regex = "^(\d\d\d\d)\-(\d\d)\-(\d\d)\s*(\d\d)\:(\d\d):(\d\d)\s*([A-Z]+)\s*(.+?)\s*\:\:\s*(.*)$"
finalData = [] final_data = []
normal_data = []
truncate = []
repeated = None
num_lines = 0
numLines = 0 if os.path.isfile(logger.sb_log_instance.log_file_path):
lastLine = False for x in logger.sb_log_instance.reverse_readline(logger.sb_log_instance.log_file_path):
numToShow = min(50, len(data))
for x in reversed(data):
x = x.decode('utf-8') x = x.decode('utf-8')
match = re.match(regex, x) match = re.match(regex, x)
@ -1260,25 +1257,43 @@ class CMD_Logs(ApiCall):
if match: if match:
level = match.group(7) level = match.group(7)
if level not in logger.reverseNames: if level not in logger.reverseNames:
lastLine = False normal_data = []
continue continue
if logger.reverseNames[level] >= minLevel: if logger.reverseNames[level] >= min_level:
lastLine = True if truncate and not normal_data and truncate[0] == match.group(8) + match.group(9):
finalData.append(x.rstrip("\n")) truncate += [match.group(8) + match.group(9)]
repeated = x
continue
if 1 < len(truncate):
final_data[-1] = repeated.strip() + ' (... %s repeat lines)\n' % len(truncate)
truncate = [match.group(8) + match.group(9)]
final_data.append(x)
if any(normal_data):
final_data += ['%02s) %s' % (n + 1, x) for n, x in enumerate(normal_data[::-1])] + \
['<br />']
num_lines += len(normal_data)
normal_data = []
else: else:
lastLine = False normal_data = []
continue continue
elif lastLine: else:
finalData.append("AA" + x) if not any(normal_data) and not any([x.strip()]):
continue
numLines += 1 normal_data.append(re.sub(r'\r?\n', '<br />', x.replace('<', '&lt;').replace('>', '&gt;')))
if numLines >= numToShow: num_lines += 1
if num_lines >= max_lines:
break break
return _responds(RESULT_SUCCESS, finalData) return _responds(RESULT_SUCCESS, final_data)
class CMD_PostProcess(ApiCall): class CMD_PostProcess(ApiCall):
_help = {"desc": "Manual postprocess TV Download Dir", _help = {"desc": "Manual postprocess TV Download Dir",

View file

@ -22,6 +22,7 @@ from __future__ import with_statement
import base64 import base64
import datetime import datetime
import dateutil.parser import dateutil.parser
import glob
import itertools import itertools
import os import os
import random import random
@ -78,20 +79,18 @@ except ImportError:
class PageTemplate(Template): class PageTemplate(Template):
def __init__(self, headers, *args, **kwargs): def __init__(self, headers, *args, **kwargs):
self.sbHost = (re.match('(?msx)^' + (('[^:]+', '\[.*\]')['[' == headers['Host'][0]]), headers['Host']).group(0), self.sbHost = headers.get('X-Forwarded-Host')
headers.get('X-Forwarded-Host', ''))['X-Forwarded-Host' in headers] if None is self.sbHost:
sbHost = headers.get('Host') or 'localhost'
self.sbHost = re.match('(?msx)^' + (('[^:]+', '\[.*\]')['[' == sbHost[0]]), sbHost).group(0)
self.sbHttpPort = sickbeard.WEB_PORT self.sbHttpPort = sickbeard.WEB_PORT
self.sbHttpsPort = (self.sbHttpPort, headers.get('X-Forwarded-Port', ''))['X-Forwarded-Port' in headers] self.sbHttpsPort = headers.get('X-Forwarded-Port') or self.sbHttpPort
self.sbRoot = sickbeard.WEB_ROOT self.sbRoot = sickbeard.WEB_ROOT
self.sbHttpsEnabled = (sickbeard.ENABLE_HTTPS, 'https' == headers.get('X-Forwarded-Proto', ''))[ self.sbHttpsEnabled = 'https' == headers.get('X-Forwarded-Proto') or sickbeard.ENABLE_HTTPS
'X-Forwarded-Proto' in headers]
self.sbHandleReverseProxy = sickbeard.HANDLE_REVERSE_PROXY self.sbHandleReverseProxy = sickbeard.HANDLE_REVERSE_PROXY
self.sbThemeName = sickbeard.THEME_NAME self.sbThemeName = sickbeard.THEME_NAME
log_page_title = 'Logs &amp; Errors' self.log_num_errors = len(classes.ErrorViewer.errors)
if len(classes.ErrorViewer.errors):
log_page_title += ' (%s)' % len(classes.ErrorViewer.errors)
self.logPageTitle = log_page_title
self.sbPID = str(sickbeard.PID) self.sbPID = str(sickbeard.PID)
self.menu = [ self.menu = [
{'title': 'Home', 'key': 'home'}, {'title': 'Home', 'key': 'home'},
@ -99,7 +98,6 @@ class PageTemplate(Template):
{'title': 'History', 'key': 'history'}, {'title': 'History', 'key': 'history'},
{'title': 'Manage', 'key': 'manage'}, {'title': 'Manage', 'key': 'manage'},
{'title': 'Config', 'key': 'config'}, {'title': 'Config', 'key': 'config'},
{'title': log_page_title, 'key': 'errorlogs'},
] ]
kwargs['file'] = os.path.join(sickbeard.PROG_DIR, 'gui/%s/interfaces/default/' % kwargs['file'] = os.path.join(sickbeard.PROG_DIR, 'gui/%s/interfaces/default/' %
@ -133,30 +131,34 @@ class BaseHandler(RequestHandler):
def get_current_user(self, *args, **kwargs): def get_current_user(self, *args, **kwargs):
if sickbeard.WEB_USERNAME or sickbeard.WEB_PASSWORD: if sickbeard.WEB_USERNAME or sickbeard.WEB_PASSWORD:
return self.get_secure_cookie('sickgear-session') return self.get_secure_cookie('sickgear-session-%s' % helpers.md5_for_text(sickbeard.WEB_PORT))
else:
return True return True
def showPoster(self, show=None, which=None, api=None): def showPoster(self, show=None, which=None, api=None):
# Redirect initial poster/banner thumb to default images # Redirect initial poster/banner thumb to default images
if which[0:6] == 'poster': if 'poster' == which[0:6]:
default_image_name = 'poster.png' default_image_name = 'poster.png'
else: elif 'banner' == which[0:6]:
default_image_name = 'banner.png' default_image_name = 'banner.png'
else:
default_image_name = 'backart.png'
static_image_path = os.path.join('/images', default_image_name) static_image_path = os.path.join('/images', default_image_name)
if show and sickbeard.helpers.findCertainShow(sickbeard.showList, int(show)): if show and sickbeard.helpers.findCertainShow(sickbeard.showList, int(show)):
cache_obj = image_cache.ImageCache() cache_obj = image_cache.ImageCache()
image_file_name = None image_file_name = None
if which == 'poster': if 'poster' == which:
image_file_name = cache_obj.poster_path(show) image_file_name = cache_obj.poster_path(show)
if which == 'poster_thumb': elif 'poster_thumb' == which:
image_file_name = cache_obj.poster_thumb_path(show) image_file_name = cache_obj.poster_thumb_path(show)
if which == 'banner': elif 'banner' == which:
image_file_name = cache_obj.banner_path(show) image_file_name = cache_obj.banner_path(show)
if which == 'banner_thumb': elif 'banner_thumb' == which:
image_file_name = cache_obj.banner_thumb_path(show) image_file_name = cache_obj.banner_thumb_path(show)
elif 'fanart' == which[0:6]:
image_file_name = cache_obj.fanart_path('%s%s' % (
show, re.sub('.*?fanart_(\d+(?:\.\w{1,20})?\.(?:\w{5,8})).*', r'.\1', which, 0, re.I)))
if ek.ek(os.path.isfile, image_file_name): if ek.ek(os.path.isfile, image_file_name):
static_image_path = image_file_name static_image_path = image_file_name
@ -188,7 +190,8 @@ class LoginHandler(BaseHandler):
if (self.get_argument('username') == username) and (self.get_argument('password') == password): if (self.get_argument('username') == username) and (self.get_argument('password') == password):
remember_me = int(self.get_argument('remember_me', default=0) or 0) remember_me = int(self.get_argument('remember_me', default=0) or 0)
self.set_secure_cookie('sickgear-session', sickbeard.COOKIE_SECRET, expires_days=30 if remember_me > 0 else None) self.set_secure_cookie('sickgear-session-%s' % helpers.md5_for_text(sickbeard.WEB_PORT),
sickbeard.COOKIE_SECRET, expires_days=30 if remember_me > 0 else None)
self.redirect(self.get_argument('next', '/home/')) self.redirect(self.get_argument('next', '/home/'))
else: else:
next_arg = '&next=' + self.get_argument('next', '/home/') next_arg = '&next=' + self.get_argument('next', '/home/')
@ -197,7 +200,7 @@ class LoginHandler(BaseHandler):
class LogoutHandler(BaseHandler): class LogoutHandler(BaseHandler):
def get(self, *args, **kwargs): def get(self, *args, **kwargs):
self.clear_cookie('sickgear-session') self.clear_cookie('sickgear-session-%s' % helpers.md5_for_text(sickbeard.WEB_PORT))
self.redirect('/login/') self.redirect('/login/')
@ -251,10 +254,10 @@ class CalendarHandler(BaseHandler):
ical += 'BEGIN:VEVENT%s' % crlf\ ical += 'BEGIN:VEVENT%s' % crlf\
+ 'DTSTART:%sT%sZ%s' % (air_date_time.strftime('%Y%m%d'), air_date_time.strftime('%H%M%S'), crlf)\ + 'DTSTART:%sT%sZ%s' % (air_date_time.strftime('%Y%m%d'), air_date_time.strftime('%H%M%S'), crlf)\
+ 'DTEND:%sT%sZ%s' % (air_date_time_end.strftime('%Y%m%d'), air_date_time_end.strftime('%H%M%S'), crlf)\ + 'DTEND:%sT%sZ%s' % (air_date_time_end.strftime('%Y%m%d'), air_date_time_end.strftime('%H%M%S'), crlf)\
+ 'SUMMARY:%s - %sx%s - %s%s' % (show['show_name'], str(episode['season']), str(episode['episode']), episode['name'], crlf)\ + u'SUMMARY:%s - %sx%s - %s%s' % (show['show_name'], episode['season'], episode['episode'], episode['name'], crlf)\
+ 'UID:%s-%s-%s-E%sS%s%s' % (appname, str(datetime.date.today().isoformat()), show['show_name'].replace(' ', '-'), str(episode['episode']), str(episode['season']), crlf)\ + u'UID:%s-%s-%s-E%sS%s%s' % (appname, datetime.date.today().isoformat(), show['show_name'].replace(' ', '-'), episode['episode'], episode['season'], crlf)\
+ 'DESCRIPTION:%s on %s' % ((show['airs'] or '(Unknown airs)'), (show['network'] or 'Unknown network'))\ + u'DESCRIPTION:%s on %s' % ((show['airs'] or '(Unknown airs)'), (show['network'] or 'Unknown network'))\
+ ('' if not episode['description'] else '%s%s' % (nl, episode['description'].splitlines()[0]))\ + ('' if not episode['description'] else u'%s%s' % (nl, episode['description'].splitlines()[0]))\
+ '%sEND:VEVENT%s' % (crlf, crlf) + '%sEND:VEVENT%s' % (crlf, crlf)
# Ending the iCal # Ending the iCal
@ -389,21 +392,6 @@ class MainHandler(WebHandler):
sickbeard.POSTER_SORTDIR = int(direction) sickbeard.POSTER_SORTDIR = int(direction)
sickbeard.save_config() sickbeard.save_config()
def setHistoryLayout(self, layout):
if layout not in ('compact', 'detailed'):
layout = 'detailed'
sickbeard.HISTORY_LAYOUT = layout
self.redirect('/history/')
def toggleDisplayShowSpecials(self, show):
sickbeard.DISPLAY_SHOW_SPECIALS = not sickbeard.DISPLAY_SHOW_SPECIALS
self.redirect('/home/displayShow?show=' + show)
def setEpisodeViewLayout(self, layout): def setEpisodeViewLayout(self, layout):
if layout not in ('poster', 'banner', 'list', 'daybyday'): if layout not in ('poster', 'banner', 'list', 'daybyday'):
layout = 'banner' layout = 'banner'
@ -425,6 +413,15 @@ class MainHandler(WebHandler):
self.redirect('/episodeView/') self.redirect('/episodeView/')
def setEpisodeViewCards(self, redir=0, *args, **kwargs):
sickbeard.EPISODE_VIEW_POSTERS = not sickbeard.EPISODE_VIEW_POSTERS
sickbeard.save_config()
if int(redir):
self.redirect('/episodeView/')
def setEpisodeViewSort(self, sort, redir=1): def setEpisodeViewSort(self, sort, redir=1):
if sort not in ('time', 'network', 'show'): if sort not in ('time', 'network', 'show'):
sort = 'time' sort = 'time'
@ -497,18 +494,40 @@ class MainHandler(WebHandler):
return (remove_article(value.lower()), value.lower())[sickbeard.SORT_ARTICLE] return (remove_article(value.lower()), value.lower())[sickbeard.SORT_ARTICLE]
# add localtime to the dict # add localtime to the dict
cache_obj = image_cache.ImageCache()
t = PageTemplate(headers=self.request.headers, file='episodeView.tmpl')
t.fanart = {}
for index, item in enumerate(sql_results): for index, item in enumerate(sql_results):
sql_results[index]['localtime'] = sbdatetime.sbdatetime.convert_to_setting(network_timezones.parse_date_time(item['airdate'], sql_results[index]['localtime'] = sbdatetime.sbdatetime.convert_to_setting(network_timezones.parse_date_time(item['airdate'],
item['airs'], item['network'])) item['airs'], item['network']))
sql_results[index]['data_show_name'] = value_maybe_article(item['show_name']) sql_results[index]['data_show_name'] = value_maybe_article(item['show_name'])
sql_results[index]['data_network'] = value_maybe_article(item['network']) sql_results[index]['data_network'] = value_maybe_article(item['network'])
sql_results.sort(sorts[sickbeard.EPISODE_VIEW_SORT]) show_id = item['showid']
if show_id in t.fanart:
continue
t = PageTemplate(headers=self.request.headers, file='episodeView.tmpl') for img in ek.ek(glob.glob, cache_obj.fanart_path(show_id).replace('fanart.jpg', '*')) or []:
t.next_week = datetime.datetime.combine(next_week_dt, datetime.time(tzinfo=network_timezones.sb_timezone)) match = re.search(r'\.(\d+(?:\.\w*)?\.(?:\w{5,8}))\.fanart\.', img, re.I)
t.today = datetime.datetime.now(network_timezones.sb_timezone) if not match:
t.sql_results = sql_results continue
fanart = [(match.group(1), sickbeard.FANART_RATINGS.get(str(show_id), {}).get(match.group(1), ''))]
if show_id not in t.fanart:
t.fanart[show_id] = fanart
else:
t.fanart[show_id] += fanart
for show in t.fanart:
fanart_rating = [(n, v) for n, v in t.fanart[show] if 20 == v]
if fanart_rating:
t.fanart[show] = fanart_rating
else:
rnd = [(n, v) for (n, v) in t.fanart[show] if 30 != v]
grouped = [(n, v) for (n, v) in rnd if 10 == v]
if grouped:
t.fanart[show] = [grouped[random.randint(0, len(grouped) - 1)]]
elif rnd:
t.fanart[show] = [rnd[random.randint(0, len(rnd) - 1)]]
# Allow local overriding of layout parameter # Allow local overriding of layout parameter
if layout and layout in ('banner', 'daybyday', 'list', 'poster'): if layout and layout in ('banner', 'daybyday', 'list', 'poster'):
@ -516,8 +535,77 @@ class MainHandler(WebHandler):
else: else:
t.layout = sickbeard.EPISODE_VIEW_LAYOUT t.layout = sickbeard.EPISODE_VIEW_LAYOUT
t.has_art = bool(len(t.fanart))
t.css = ' '.join([t.layout] +
([], [('landscape', 'portrait')[sickbeard.EPISODE_VIEW_POSTERS]])['daybyday' == t.layout] +
([], ['back-art'])[sickbeard.EPISODE_VIEW_BACKGROUND and t.has_art] +
([], ['translucent'])[sickbeard.EPISODE_VIEW_BACKGROUND_TRANSLUCENT] +
[{0: 'reg', 1: 'pro', 2: 'pro ii'}.get(sickbeard.EPISODE_VIEW_VIEWMODE)])
t.fanart_panel = sickbeard.FANART_PANEL
sql_results.sort(sorts[sickbeard.EPISODE_VIEW_SORT])
t.next_week = datetime.datetime.combine(next_week_dt, datetime.time(tzinfo=network_timezones.sb_timezone))
t.today = datetime.datetime.now(network_timezones.sb_timezone)
t.sql_results = sql_results
return t.respond() return t.respond()
def live_panel(self, *args, **kwargs):
if 'allseasons' in kwargs:
sickbeard.DISPLAY_SHOW_MINIMUM = bool(config.minimax(kwargs['allseasons'], 0, 0, 1))
elif 'rate' in kwargs:
which = kwargs['which'].replace('fanart_', '')
rating = int(kwargs['rate'])
if rating:
sickbeard.FANART_RATINGS.setdefault(kwargs['show'], {}).update({which: rating})
elif sickbeard.FANART_RATINGS.get(kwargs['show'], {}).get(which):
del sickbeard.FANART_RATINGS[kwargs['show']][which]
if not sickbeard.FANART_RATINGS[kwargs['show']]:
del sickbeard.FANART_RATINGS[kwargs['show']]
else:
translucent = bool(config.minimax(kwargs.get('translucent'), 0, 0, 1))
backart = bool(config.minimax(kwargs.get('backart'), 0, 0, 1))
viewmode = config.minimax(kwargs.get('viewmode'), 0, 0, 2)
if 'ds' == kwargs.get('pg', None):
if 'viewart' in kwargs:
sickbeard.DISPLAY_SHOW_VIEWART = config.minimax(kwargs['viewart'], 0, 0, 2)
elif 'translucent' in kwargs:
sickbeard.DISPLAY_SHOW_BACKGROUND_TRANSLUCENT = translucent
elif 'backart' in kwargs:
sickbeard.DISPLAY_SHOW_BACKGROUND = backart
elif 'viewmode' in kwargs:
sickbeard.DISPLAY_SHOW_VIEWMODE = viewmode
elif 'ev' == kwargs.get('pg', None):
if 'translucent' in kwargs:
sickbeard.EPISODE_VIEW_BACKGROUND_TRANSLUCENT = translucent
elif 'backart' in kwargs:
sickbeard.EPISODE_VIEW_BACKGROUND = backart
sickbeard.FANART_PANEL = 'highlight-off' == sickbeard.FANART_PANEL and 'highlight-off' or \
'highlight2' == sickbeard.FANART_PANEL and 'highlight1' or \
'highlight1' == sickbeard.FANART_PANEL and 'highlight' or 'highlight-off'
elif 'viewmode' in kwargs:
sickbeard.EPISODE_VIEW_VIEWMODE = viewmode
sickbeard.save_config()
def toggleDisplayShowSpecials(self, show):
sickbeard.DISPLAY_SHOW_SPECIALS = not sickbeard.DISPLAY_SHOW_SPECIALS
self.redirect('/home/displayShow?show=' + show)
def setHistoryLayout(self, layout):
if layout not in ('compact', 'detailed'):
layout = 'detailed'
sickbeard.HISTORY_LAYOUT = layout
self.redirect('/history/')
def _genericMessage(self, subject, message): def _genericMessage(self, subject, message):
t = PageTemplate(headers=self.request.headers, file='genericMessage.tmpl') t = PageTemplate(headers=self.request.headers, file='genericMessage.tmpl')
t.submenu = self.HomeMenu() t.submenu = self.HomeMenu()
@ -529,7 +617,6 @@ class MainHandler(WebHandler):
class Home(MainHandler): class Home(MainHandler):
def HomeMenu(self): def HomeMenu(self):
return [ return [
{'title': 'Add Shows', 'path': 'home/addShows/', },
{'title': 'Manual Post-Processing', 'path': 'home/postprocess/'}, {'title': 'Manual Post-Processing', 'path': 'home/postprocess/'},
{'title': 'Update Emby', 'path': 'home/updateEMBY/', 'requires': self.haveEMBY}, {'title': 'Update Emby', 'path': 'home/updateEMBY/', 'requires': self.haveEMBY},
{'title': 'Update Kodi', 'path': 'home/updateKODI/', 'requires': self.haveKODI}, {'title': 'Update Kodi', 'path': 'home/updateKODI/', 'requires': self.haveKODI},
@ -606,6 +693,13 @@ class Home(MainHandler):
if 0 == len(t.showlists): if 0 == len(t.showlists):
t.showlists.append(['container0', 'Show List', sickbeard.showList]) t.showlists.append(['container0', 'Show List', sickbeard.showList])
else:
items = []
default = 0
for index, group in enumerate(t.showlists):
items += group[2]
default = (default, index)['Show List' == group[1]]
t.showlists[default][2] += [show for show in sickbeard.showList if show not in items]
if 'simple' != sickbeard.HOME_LAYOUT: if 'simple' != sickbeard.HOME_LAYOUT:
t.network_images = {} t.network_images = {}
@ -1143,6 +1237,44 @@ class Home(MainHandler):
else: else:
self.redirect('/home/') self.redirect('/home/')
def display_season(self, show=None, season=None):
response = {'success': False}
show_obj = None
if show:
show_obj = sickbeard.helpers.findCertainShow(sickbeard.showList, helpers.tryInt(show, -1))
if not show_obj:
return json.dumps(response)
re_season = re.compile('(?i)^showseason-(\d+)$')
season = None if not any(re_season.findall(season)) else \
helpers.tryInt(re_season.findall(season)[0], None)
if None is season:
return json.dumps(response)
t = PageTemplate(headers=self.request.headers, file='inc_displayShow.tmpl')
t.show = show_obj
my_db = db.DBConnection()
sql_results = my_db.select('SELECT * FROM tv_episodes WHERE showid = ? AND season = ? ORDER BY episode DESC',
[show_obj.indexerid, season])
t.episodes = sql_results
ep_cats = {}
for row in sql_results:
status_overview = show_obj.getOverview(int(row['status']))
if status_overview:
ep_cats['%sx%s' % (season, row['episode'])] = status_overview
t.ep_cats = ep_cats
args = (int(show_obj.indexerid), int(show_obj.indexer))
t.scene_numbering = get_scene_numbering_for_show(*args)
t.xem_numbering = get_xem_numbering_for_show(*args)
t.scene_absolute_numbering = get_scene_absolute_numbering_for_show(*args)
t.xem_absolute_numbering = get_xem_absolute_numbering_for_show(*args)
return json.dumps({'success': t.respond()})
def displayShow(self, show=None): def displayShow(self, show=None):
if show is None: if show is None:
@ -1153,17 +1285,6 @@ class Home(MainHandler):
if showObj is None: if showObj is None:
return self._genericMessage('Error', 'Show not in show list') return self._genericMessage('Error', 'Show not in show list')
myDB = db.DBConnection()
seasonResults = myDB.select(
'SELECT DISTINCT season FROM tv_episodes WHERE showid = ? ORDER BY season desc',
[showObj.indexerid]
)
sqlResults = myDB.select(
'SELECT * FROM tv_episodes WHERE showid = ? ORDER BY season DESC, episode DESC',
[showObj.indexerid]
)
t = PageTemplate(headers=self.request.headers, file='displayShow.tmpl') t = PageTemplate(headers=self.request.headers, file='displayShow.tmpl')
t.submenu = [{'title': 'Edit', 'path': 'home/editShow?show=%d' % showObj.indexerid}] t.submenu = [{'title': 'Edit', 'path': 'home/editShow?show=%d' % showObj.indexerid}]
@ -1195,13 +1316,14 @@ class Home(MainHandler):
elif sickbeard.showQueueScheduler.action.isInSubtitleQueue(showObj): # @UndefinedVariable elif sickbeard.showQueueScheduler.action.isInSubtitleQueue(showObj): # @UndefinedVariable
show_message = 'This show is queued and awaiting subtitles download.' show_message = 'This show is queued and awaiting subtitles download.'
t.force_update = 'home/updateShow?show=%d&amp;force=1&amp;web=1' % showObj.indexerid
if not sickbeard.showQueueScheduler.action.isBeingAdded(showObj): # @UndefinedVariable if not sickbeard.showQueueScheduler.action.isBeingAdded(showObj): # @UndefinedVariable
if not sickbeard.showQueueScheduler.action.isBeingUpdated(showObj): # @UndefinedVariable if not sickbeard.showQueueScheduler.action.isBeingUpdated(showObj): # @UndefinedVariable
t.submenu.append( t.submenu.append(
{'title': 'Remove', 'path': 'home/deleteShow?show=%d' % showObj.indexerid, 'confirm': True}) {'title': 'Remove', 'path': 'home/deleteShow?show=%d' % showObj.indexerid, 'confirm': True})
t.submenu.append({'title': 'Re-scan files', 'path': 'home/refreshShow?show=%d' % showObj.indexerid}) t.submenu.append({'title': 'Re-scan files', 'path': 'home/refreshShow?show=%d' % showObj.indexerid})
t.submenu.append( t.submenu.append(
{'title': 'Force Full Update', 'path': 'home/updateShow?show=%d&amp;force=1&amp;web=1' % showObj.indexerid}) {'title': 'Force Full Update', 'path': t.force_update})
t.submenu.append({'title': 'Update show in Emby', t.submenu.append({'title': 'Update show in Emby',
'path': 'home/updateEMBY%s' % 'path': 'home/updateEMBY%s' %
(INDEXER_TVDB == showObj.indexer and ('?show=%s' % showObj.indexerid) or '/'), (INDEXER_TVDB == showObj.indexer and ('?show=%s' % showObj.indexerid) or '/'),
@ -1219,56 +1341,81 @@ class Home(MainHandler):
{'title': 'Download Subtitles', 'path': 'home/subtitleShow?show=%d' % showObj.indexerid}) {'title': 'Download Subtitles', 'path': 'home/subtitleShow?show=%d' % showObj.indexerid})
t.show = showObj t.show = showObj
t.sqlResults = sqlResults
t.seasonResults = seasonResults
t.show_message = show_message t.show_message = show_message
epCounts = {} ep_counts = {}
epCats = {} ep_cats = {}
epCounts[Overview.SKIPPED] = 0 ep_counts[Overview.SKIPPED] = 0
epCounts[Overview.WANTED] = 0 ep_counts[Overview.WANTED] = 0
epCounts[Overview.QUAL] = 0 ep_counts[Overview.QUAL] = 0
epCounts[Overview.GOOD] = 0 ep_counts[Overview.GOOD] = 0
epCounts[Overview.UNAIRED] = 0 ep_counts[Overview.UNAIRED] = 0
epCounts[Overview.SNATCHED] = 0 ep_counts[Overview.SNATCHED] = 0
epCounts['videos'] = {} ep_counts['videos'] = {}
epCounts['archived'] = {} ep_counts['status'] = {}
epCounts['totals'] = {} ep_counts['archived'] = {}
highest_season = 0 ep_counts['totals'] = {}
latest_season = 0 ep_counts['eps_most'] = 0
ep_counts['eps_all'] = 0
t.latest_season = 0
t.has_special = False
for curResult in sqlResults: my_db = db.DBConnection()
curEpCat = showObj.getOverview(int(curResult['status']))
if curEpCat:
epCats[str(curResult['season']) + 'x' + str(curResult['episode'])] = curEpCat
epCounts[curEpCat] += 1
if '' != curResult['location']:
if curResult['season'] not in epCounts['videos']:
epCounts['videos'][curResult['season']] = 1
else:
epCounts['videos'][curResult['season']] += 1
if curResult['season'] not in epCounts['totals']:
epCounts['totals'][curResult['season']] = 1
else:
epCounts['totals'][curResult['season']] += 1
if ARCHIVED == curResult['status']:
if curResult['season'] not in epCounts['archived']:
epCounts['archived'][curResult['season']] = 1
else:
epCounts['archived'][curResult['season']] += 1
if highest_season < curResult['season'] and 1000 < curResult['airdate'] and UNAIRED < curResult['status']:
highest_season = curResult['season']
if 0 < len(epCounts['totals']): for row in my_db.select('SELECT season, count(*) AS cnt FROM tv_episodes WHERE showid = ?'
latest_season = int(sorted(epCounts['totals'])[-1::][0]) + ' GROUP BY season', [showObj.indexerid]):
ep_counts['totals'][row['season']] = row['cnt']
display_seasons = [] if None is not ep_counts['totals'].get(0, None):
if 1 < highest_season: t.has_special = True
display_seasons += [1] if not sickbeard.DISPLAY_SHOW_SPECIALS:
display_seasons += [highest_season] del(ep_counts['totals'][0])
ep_counts['eps_all'] = sum(ep_counts['totals'].values())
ep_counts['eps_most'] = max(ep_counts['totals'].values())
all_seasons = sorted(ep_counts['totals'].keys(), reverse=True)
t.lowest_season, t.highest_season = all_seasons[-1], all_seasons[0]
# 55 == seasons 1-10 and excludes the random season 0
force_display_show_minimum = 30 < ep_counts['eps_most'] or 55 < sum(ep_counts['totals'].keys())
display_show_minimum = sickbeard.DISPLAY_SHOW_MINIMUM or force_display_show_minimum
for row in my_db.select('SELECT max(season) as latest FROM tv_episodes WHERE showid = ?'
+ ' and 1000 < airdate and ? < status', [showObj.indexerid, UNAIRED]):
t.latest_season = row['latest']
t.season_min = ([], [1])[2 < t.latest_season] + [t.latest_season]
t.other_seasons = (list(set(all_seasons) - set(t.season_min)), [])[display_show_minimum]
t.seasons = []
for x in all_seasons:
t.seasons += [(x, [None] if x not in (t.season_min + t.other_seasons) else my_db.select(
'SELECT * FROM tv_episodes WHERE showid = ? AND season = ? ORDER BY episode DESC',
[showObj.indexerid, x]))]
for row in my_db.select('SELECT season, episode, status FROM tv_episodes WHERE showid = ? AND season IN (%s)' %
','.join(['?'] * len(t.season_min + t.other_seasons)),
[showObj.indexerid] + t.season_min + t.other_seasons):
status_overview = showObj.getOverview(row['status'])
if status_overview:
ep_cats['%sx%s' % (row['season'], row['episode'])] = status_overview
t.ep_cats = ep_cats
for row in my_db.select('SELECT season, count(*) AS cnt, status FROM tv_episodes WHERE showid = ?'
+ ' GROUP BY season, status', [showObj.indexerid]):
status_overview = showObj.getOverview(row['status'])
if status_overview:
ep_counts[status_overview] += row['cnt']
if ARCHIVED == row['status']:
ep_counts['archived'].setdefault(row['season'], row['cnt'])
else:
ep_counts['status'].setdefault(row['season'], {status_overview: row['cnt']})
for row in my_db.select('SELECT season, count(*) AS cnt FROM tv_episodes WHERE showid = ?'
+ ' AND \'\' != location GROUP BY season', [showObj.indexerid]):
ep_counts['videos'][row['season']] = row['cnt']
t.ep_counts = ep_counts
t.sortedShowLists = self.sorted_show_lists() t.sortedShowLists = self.sorted_show_lists()
tvshows = [] tvshows = []
tvshow_names = [] tvshow_names = []
cur_sel = None cur_sel = None
@ -1291,19 +1438,42 @@ class Home(MainHandler):
if showObj.is_anime: if showObj.is_anime:
t.bwl = showObj.release_groups t.bwl = showObj.release_groups
t.epCounts = epCounts
t.epCats = epCats
t.display_seasons = display_seasons
t.latest_season = latest_season
showObj.exceptions = scene_exceptions.get_scene_exceptions(showObj.indexerid) showObj.exceptions = scene_exceptions.get_scene_exceptions(showObj.indexerid)
t.fanart = []
cache_obj = image_cache.ImageCache()
for img in ek.ek(glob.glob, cache_obj.fanart_path(showObj.indexerid).replace('fanart.jpg', '*')) or []:
match = re.search(r'\.(\d+(?:\.(\w*?(\d*)))?\.(?:\w{5,8}))\.fanart\.', img, re.I)
if match and match.group(1):
t.fanart += [(match.group(1), sickbeard.FANART_RATINGS.get(show, {}).get(match.group(1), ''))]
t.start_image = None
ratings = [v for n, v in t.fanart]
if 20 in ratings:
t.start_image = ratings.index(20)
else:
rnd = [(x, v) for x, (n, v) in enumerate(t.fanart) if 30 != v]
grouped = [n for (n, v) in rnd if 10 == v]
if grouped:
t.start_image = grouped[random.randint(0, len(grouped) - 1)]
elif rnd:
t.start_image = rnd[random.randint(0, len(rnd) - 1)][0]
t.has_art = bool(len(t.fanart))
t.css = ' '.join(([], ['back-art'])[sickbeard.DISPLAY_SHOW_BACKGROUND and t.has_art] +
([], ['translucent'])[sickbeard.DISPLAY_SHOW_BACKGROUND_TRANSLUCENT] +
{0: [], 1: ['poster-right'], 2: ['poster-off']}.get(sickbeard.DISPLAY_SHOW_VIEWART) +
([], ['min'])[display_show_minimum] +
([], ['min-force'])[force_display_show_minimum] +
[{0: 'reg', 1: 'pro', 2: 'pro ii'}.get(sickbeard.DISPLAY_SHOW_VIEWMODE)])
t.clean_show_name = urllib.quote_plus(sickbeard.indexermapper.clean_show_name(showObj.name))
indexerid = int(showObj.indexerid) indexerid = int(showObj.indexerid)
indexer = int(showObj.indexer) indexer = int(showObj.indexer)
t.all_scene_exceptions = showObj.exceptions t.all_scene_exceptions = showObj.exceptions
t.scene_numbering = get_scene_numbering_for_show(indexerid, indexer) t.scene_numbering = get_scene_numbering_for_show(indexerid, indexer)
t.xem_numbering = get_xem_numbering_for_show(indexerid, indexer)
t.scene_absolute_numbering = get_scene_absolute_numbering_for_show(indexerid, indexer) t.scene_absolute_numbering = get_scene_absolute_numbering_for_show(indexerid, indexer)
t.xem_numbering = get_xem_numbering_for_show(indexerid, indexer)
t.xem_absolute_numbering = get_xem_absolute_numbering_for_show(indexerid, indexer) t.xem_absolute_numbering = get_xem_absolute_numbering_for_show(indexerid, indexer)
return t.respond() return t.respond()
@ -1320,6 +1490,28 @@ class Home(MainHandler):
results = filter(lambda x: x.tag == tag, sickbeard.showList) results = filter(lambda x: x.tag == tag, sickbeard.showList)
if results: if results:
sorted_show_lists.append([tag, sorted(results, lambda x, y: cmp(titler(x.name), titler(y.name)))]) sorted_show_lists.append([tag, sorted(results, lambda x, y: cmp(titler(x.name), titler(y.name)))])
# handle orphaned shows
if len(sickbeard.showList) != sum([len(x[1]) for x in sorted_show_lists]):
used_ids = set()
for x in sorted_show_lists:
for y in x[1]:
used_ids |= {y.indexerid}
showlist = dict()
all_ids = set(x.indexerid for x in sickbeard.showList)
for iid in list(all_ids - used_ids):
try:
show = helpers.findCertainShow(sickbeard.showList, iid)
except (StandardError, Exception):
pass
if show:
if show.tag in showlist:
showlist[show.tag] += [show]
else:
showlist[show.tag] = [show]
sorted_show_lists += [[key, shows] for key, shows in showlist.items()]
elif 'anime' == sickbeard.SHOWLIST_TAGVIEW: elif 'anime' == sickbeard.SHOWLIST_TAGVIEW:
shows = [] shows = []
anime = [] anime = []
@ -1342,7 +1534,7 @@ class Home(MainHandler):
result = myDB.select( result = myDB.select(
'SELECT description FROM tv_episodes WHERE showid = ? AND season = ? AND episode = ?', 'SELECT description FROM tv_episodes WHERE showid = ? AND season = ? AND episode = ?',
(int(show), int(season), int(episode))) (int(show), int(season), int(episode)))
return result[0]['description'] if result else 'Episode not found.' return 'Episode not found.' if not result else (result[0]['description'] or '')[:250:]
def sceneExceptions(self, show): def sceneExceptions(self, show):
exceptionsList = sickbeard.scene_exceptions.get_all_scene_exceptions(show) exceptionsList = sickbeard.scene_exceptions.get_all_scene_exceptions(show)
@ -1351,10 +1543,8 @@ class Home(MainHandler):
out = [] out = []
for season, names in iter(sorted(iteritems(exceptionsList))): for season, names in iter(sorted(iteritems(exceptionsList))):
if season == -1: out.append('S%s: %s' % ((season, '*')[-1 == season], ',<br />\n'.join(names)))
season = '*' return '---------<br />\n'.join(out)
out.append('S' + str(season) + ': ' + ', '.join(names))
return '<br/>'.join(out)
def switchIndexer(self, indexerid, indexer, mindexerid, mindexer, set_pause=False, mark_wanted=False): def switchIndexer(self, indexerid, indexer, mindexerid, mindexer, set_pause=False, mark_wanted=False):
indexer = helpers.tryInt(indexer) indexer = helpers.tryInt(indexer)
@ -1473,11 +1663,38 @@ class Home(MainHandler):
ui.notifications.message('Mapping Reloaded') ui.notifications.message('Mapping Reloaded')
return json.dumps({k: {r: w for r, w in v.iteritems() if 'date' != r} for k, v in show_obj.ids.iteritems()}) return json.dumps({k: {r: w for r, w in v.iteritems() if 'date' != r} for k, v in show_obj.ids.iteritems()})
@staticmethod
def fanart_tmpl(t):
t.fanart = []
cache_obj = image_cache.ImageCache()
for img in ek.ek(glob.glob, cache_obj.fanart_path(t.show.indexerid).replace('fanart.jpg', '*')) or []:
match = re.search(r'\.(\d+(?:\.(\w*?(\d*)))?\.(?:\w{5,8}))\.fanart\.', img, re.I)
if match and match.group(1):
t.fanart += [(match.group(1),
sickbeard.FANART_RATINGS.get(str(t.show.indexerid), {}).get(match.group(1), ''))]
t.start_image = None
ratings = [v for n, v in t.fanart]
if 20 in ratings:
t.start_image = ratings.index(20)
else:
rnd = [(x, v) for x, (n, v) in enumerate(t.fanart) if 30 != v]
grouped = [n for (n, v) in rnd if 10 == v]
if grouped:
t.start_image = grouped[random.randint(0, len(grouped) - 1)]
elif rnd:
t.start_image = rnd[random.randint(0, len(rnd) - 1)][0]
t.has_art = bool(len(t.fanart))
t.css = ' '.join(([], ['back-art'])[sickbeard.DISPLAY_SHOW_BACKGROUND and t.has_art] +
([], ['translucent'])[sickbeard.DISPLAY_SHOW_BACKGROUND_TRANSLUCENT] +
[{0: 'reg', 1: 'pro', 2: 'pro ii'}.get(sickbeard.DISPLAY_SHOW_VIEWMODE)])
def editShow(self, show=None, location=None, anyQualities=[], bestQualities=[], exceptions_list=[], def editShow(self, show=None, location=None, anyQualities=[], bestQualities=[], exceptions_list=[],
flatten_folders=None, paused=None, directCall=False, air_by_date=None, sports=None, dvdorder=None, flatten_folders=None, paused=None, directCall=False, air_by_date=None, sports=None, dvdorder=None,
indexerLang=None, subtitles=None, archive_firstmatch=None, rls_ignore_words=None, indexerLang=None, subtitles=None, archive_firstmatch=None, rls_ignore_words=None,
rls_require_words=None, anime=None, blacklist=None, whitelist=None, rls_require_words=None, anime=None, blacklist=None, whitelist=None,
scene=None, tag=None, quality_preset=None, **kwargs): scene=None, tag=None, quality_preset=None, reset_fanart=None, **kwargs):
if show is None: if show is None:
errString = 'Invalid show ID: ' + str(show) errString = 'Invalid show ID: ' + str(show)
@ -1528,6 +1745,10 @@ class Home(MainHandler):
t.show = showObj t.show = showObj
t.show_has_scene_map = showObj.indexerid in sickbeard.scene_exceptions.xem_ids_list[showObj.indexer] t.show_has_scene_map = showObj.indexerid in sickbeard.scene_exceptions.xem_ids_list[showObj.indexer]
# noinspection PyTypeChecker
self.fanart_tmpl(t)
t.num_ratings = len(sickbeard.FANART_RATINGS.get(str(t.show.indexerid), {}))
return t.respond() return t.respond()
flatten_folders = config.checkbox_to_value(flatten_folders) flatten_folders = config.checkbox_to_value(flatten_folders)
@ -1540,6 +1761,10 @@ class Home(MainHandler):
anime = config.checkbox_to_value(anime) anime = config.checkbox_to_value(anime)
subtitles = config.checkbox_to_value(subtitles) subtitles = config.checkbox_to_value(subtitles)
if config.checkbox_to_value(reset_fanart) and sickbeard.FANART_RATINGS.get(show):
del sickbeard.FANART_RATINGS[show]
sickbeard.save_config()
if indexerLang and indexerLang in sickbeard.indexerApi(showObj.indexer).indexer().config['valid_languages']: if indexerLang and indexerLang in sickbeard.indexerApi(showObj.indexer).indexer().config['valid_languages']:
indexer_lang = indexerLang indexer_lang = indexerLang
else: else:
@ -1955,14 +2180,17 @@ class Home(MainHandler):
if cur_ep_obj.location: if cur_ep_obj.location:
if cur_ep_obj.relatedEps: if cur_ep_obj.relatedEps:
# do we have one of multi-episodes in the rename list already # do we have one of multi-episodes in the rename list already
have_already = False
for cur_related_ep in cur_ep_obj.relatedEps + [cur_ep_obj]: for cur_related_ep in cur_ep_obj.relatedEps + [cur_ep_obj]:
if cur_related_ep in ep_obj_rename_list: if cur_related_ep in ep_obj_rename_list:
have_already = True
break break
if not have_already: ep_status, ep_qual = Quality.splitCompositeStatus(cur_related_ep.status)
if not ep_qual:
continue
ep_obj_rename_list.append(cur_ep_obj) ep_obj_rename_list.append(cur_ep_obj)
else: else:
ep_status, ep_qual = Quality.splitCompositeStatus(cur_ep_obj.status)
if not ep_qual:
continue
ep_obj_rename_list.append(cur_ep_obj) ep_obj_rename_list.append(cur_ep_obj)
if ep_obj_rename_list: if ep_obj_rename_list:
@ -1974,6 +2202,9 @@ class Home(MainHandler):
t.ep_obj_list = ep_obj_rename_list t.ep_obj_list = ep_obj_rename_list
t.show = showObj t.show = showObj
# noinspection PyTypeChecker
self.fanart_tmpl(t)
return t.respond() return t.respond()
def doRename(self, show=None, eps=None): def doRename(self, show=None, eps=None):
@ -3214,7 +3445,7 @@ class NewHomeAddShows(Home):
return t.respond() return t.respond()
def existing_shows(self, *args, **kwargs): def import_shows(self, *args, **kwargs):
""" """
Prints out the page to add existing shows from a root dir Prints out the page to add existing shows from a root dir
""" """
@ -3269,7 +3500,7 @@ class NewHomeAddShows(Home):
logger.log('Unable to add show due to show selection. Not enough arguments: %s' % (repr(series_pieces)), logger.log('Unable to add show due to show selection. Not enough arguments: %s' % (repr(series_pieces)),
logger.ERROR) logger.ERROR)
ui.notifications.error('Unknown error. Unable to add show due to problem with show selection.') ui.notifications.error('Unknown error. Unable to add show due to problem with show selection.')
return self.redirect('/home/addShows/existing_shows/') return self.redirect('/home/addShows/import_shows/')
indexer = int(series_pieces[0]) indexer = int(series_pieces[0])
indexer_id = int(series_pieces[2]) indexer_id = int(series_pieces[2])
@ -3292,7 +3523,7 @@ class NewHomeAddShows(Home):
# blanket policy - if the dir exists you should have used 'add existing show' numbnuts # blanket policy - if the dir exists you should have used 'add existing show' numbnuts
if ek.ek(os.path.isdir, show_dir) and not fullShowPath: if ek.ek(os.path.isdir, show_dir) and not fullShowPath:
ui.notifications.error('Unable to add show', u'Found existing folder: ' + show_dir) ui.notifications.error('Unable to add show', u'Found existing folder: ' + show_dir)
return self.redirect('/home/addShows/existing_shows?sid=%s&hash_dir=%s' % (indexer_id, abs(hash(show_dir)))) return self.redirect('/home/addShows/import_shows?sid=%s&hash_dir=%s' % (indexer_id, abs(hash(show_dir))))
# don't create show dir if config says not to # don't create show dir if config says not to
if sickbeard.ADD_SHOWS_WO_DIR: if sickbeard.ADD_SHOWS_WO_DIR:
@ -4381,34 +4612,41 @@ class ConfigGeneral(Config):
proxy_setting=None, proxy_indexers=None, anon_redirect=None, git_path=None, git_remote=None, calendar_unprotected=None, proxy_setting=None, proxy_indexers=None, anon_redirect=None, git_path=None, git_remote=None, calendar_unprotected=None,
fuzzy_dating=None, trim_zero=None, date_preset=None, date_preset_na=None, time_preset=None, fuzzy_dating=None, trim_zero=None, date_preset=None, date_preset_na=None, time_preset=None,
indexer_timeout=None, rootDir=None, theme_name=None, default_home=None, use_imdb_info=None, indexer_timeout=None, rootDir=None, theme_name=None, default_home=None, use_imdb_info=None,
show_tags=None, showlist_tagview=None): fanart_limit=None, show_tags=None, showlist_tagview=None):
results = [] results = []
# Misc # Misc
sickbeard.LAUNCH_BROWSER = config.checkbox_to_value(launch_browser) sickbeard.LAUNCH_BROWSER = config.checkbox_to_value(launch_browser)
config.change_VERSION_NOTIFY(config.checkbox_to_value(version_notify))
sickbeard.AUTO_UPDATE = config.checkbox_to_value(auto_update)
sickbeard.NOTIFY_ON_UPDATE = config.checkbox_to_value(notify_on_update)
# sickbeard.LOG_DIR is set in config.change_LOG_DIR()
sickbeard.UPDATE_SHOWS_ON_START = config.checkbox_to_value(update_shows_on_start) sickbeard.UPDATE_SHOWS_ON_START = config.checkbox_to_value(update_shows_on_start)
sickbeard.SHOW_UPDATE_HOUR = config.minimax(show_update_hour, 3, 0, 23) sickbeard.SHOW_UPDATE_HOUR = config.minimax(show_update_hour, 3, 0, 23)
sickbeard.TRASH_REMOVE_SHOW = config.checkbox_to_value(trash_remove_show) sickbeard.TRASH_REMOVE_SHOW = config.checkbox_to_value(trash_remove_show)
sickbeard.TRASH_ROTATE_LOGS = config.checkbox_to_value(trash_rotate_logs) sickbeard.TRASH_ROTATE_LOGS = config.checkbox_to_value(trash_rotate_logs)
if not config.change_LOG_DIR(log_dir, web_log):
results += ['Unable to create directory ' + os.path.normpath(log_dir) + ', log directory not changed.']
if indexer_default:
sickbeard.INDEXER_DEFAULT = config.to_int(indexer_default)
if not sickbeard.indexerApi(sickbeard.INDEXER_DEFAULT).config['active']:
sickbeard.INDEXER_DEFAULT = INDEXER_TVDB
if indexer_timeout:
sickbeard.INDEXER_TIMEOUT = config.to_int(indexer_timeout)
# Updates
config.change_VERSION_NOTIFY(config.checkbox_to_value(version_notify))
sickbeard.AUTO_UPDATE = config.checkbox_to_value(auto_update)
config.change_UPDATE_FREQUENCY(update_frequency) config.change_UPDATE_FREQUENCY(update_frequency)
sickbeard.LAUNCH_BROWSER = config.checkbox_to_value(launch_browser) sickbeard.NOTIFY_ON_UPDATE = config.checkbox_to_value(notify_on_update)
sickbeard.HOME_SEARCH_FOCUS = config.checkbox_to_value(home_search_focus)
sickbeard.USE_IMDB_INFO = config.checkbox_to_value(use_imdb_info) # Interface
sickbeard.SORT_ARTICLE = config.checkbox_to_value(sort_article) sickbeard.THEME_NAME = theme_name
sickbeard.CPU_PRESET = cpu_preset sickbeard.DEFAULT_HOME = default_home
sickbeard.FILE_LOGGING_PRESET = file_logging_preset sickbeard.FANART_LIMIT = config.minimax(fanart_limit, 3, 0, 500)
sickbeard.SHOWLIST_TAGVIEW = showlist_tagview sickbeard.SHOWLIST_TAGVIEW = showlist_tagview
# 'Show List' is the must have default fallback. Tags in use that are removed from config ui are restored, not deleted. # 'Show List' is the must have default fallback. Tags in use that are removed from config ui are restored,
# Deduped list order preservation is key to feature function. # not deleted. Deduped list order preservation is key to feature function.
myDB = db.DBConnection() my_db = db.DBConnection()
sql_results = myDB.select('SELECT DISTINCT tag FROM tv_shows') sql_results = my_db.select('SELECT DISTINCT tag FROM tv_shows')
new_names = [u'' + v.strip() for v in (show_tags.split(u','), [])[None is show_tags] if v.strip()] new_names = [u'' + v.strip() for v in (show_tags.split(u','), [])[None is show_tags] if v.strip()]
orphans = [item for item in [v['tag'] for v in sql_results or []] if item not in new_names] orphans = [item for item in [v['tag'] for v in sql_results or []] if item not in new_names]
cleanser = [] cleanser = []
@ -4419,75 +4657,60 @@ class ConfigGeneral(Config):
sickbeard.SHOW_TAGS = [dedupe.setdefault(item, item) for item in (cleanser + new_names + [u'Show List']) sickbeard.SHOW_TAGS = [dedupe.setdefault(item, item) for item in (cleanser + new_names + [u'Show List'])
if item not in dedupe] if item not in dedupe]
logger.log_set_level() sickbeard.HOME_SEARCH_FOCUS = config.checkbox_to_value(home_search_focus)
sickbeard.USE_IMDB_INFO = config.checkbox_to_value(use_imdb_info)
sickbeard.ANON_REDIRECT = anon_redirect sickbeard.SORT_ARTICLE = config.checkbox_to_value(sort_article)
sickbeard.PROXY_SETTING = proxy_setting sickbeard.FUZZY_DATING = config.checkbox_to_value(fuzzy_dating)
sickbeard.PROXY_INDEXERS = config.checkbox_to_value(proxy_indexers) sickbeard.TRIM_ZERO = config.checkbox_to_value(trim_zero)
sickbeard.GIT_PATH = git_path if date_preset:
sickbeard.GIT_REMOTE = git_remote sickbeard.DATE_PRESET = date_preset
sickbeard.CALENDAR_UNPROTECTED = config.checkbox_to_value(calendar_unprotected) if time_preset:
# sickbeard.LOG_DIR is set in config.change_LOG_DIR() sickbeard.TIME_PRESET_W_SECONDS = time_preset
sickbeard.TIME_PRESET = sickbeard.TIME_PRESET_W_SECONDS.replace(u':%S', u'')
sickbeard.WEB_PORT = config.to_int(web_port) sickbeard.TIMEZONE_DISPLAY = timezone_display
sickbeard.WEB_IPV6 = config.checkbox_to_value(web_ipv6)
# sickbeard.WEB_LOG is set in config.change_LOG_DIR()
sickbeard.ENCRYPTION_VERSION = config.checkbox_to_value(encryption_version)
# Web interface
reload_page = False reload_page = False
if sickbeard.WEB_USERNAME != web_username: if sickbeard.WEB_USERNAME != web_username:
sickbeard.WEB_USERNAME = web_username sickbeard.WEB_USERNAME = web_username
reload_page = True reload_page = True
if set('*') != set(web_password): if set('*') != set(web_password):
sickbeard.WEB_PASSWORD = web_password sickbeard.WEB_PASSWORD = web_password
reload_page = True reload_page = True
sickbeard.FUZZY_DATING = config.checkbox_to_value(fuzzy_dating) sickbeard.CALENDAR_UNPROTECTED = config.checkbox_to_value(calendar_unprotected)
sickbeard.TRIM_ZERO = config.checkbox_to_value(trim_zero)
if date_preset:
sickbeard.DATE_PRESET = date_preset
if indexer_default:
sickbeard.INDEXER_DEFAULT = config.to_int(indexer_default)
if not sickbeard.indexerApi(sickbeard.INDEXER_DEFAULT).config['active']:
sickbeard.INDEXER_DEFAULT = INDEXER_TVDB
if indexer_timeout:
sickbeard.INDEXER_TIMEOUT = config.to_int(indexer_timeout)
if time_preset:
sickbeard.TIME_PRESET_W_SECONDS = time_preset
sickbeard.TIME_PRESET = sickbeard.TIME_PRESET_W_SECONDS.replace(u':%S', u'')
sickbeard.TIMEZONE_DISPLAY = timezone_display
if not config.change_LOG_DIR(log_dir, web_log):
results += ['Unable to create directory ' + os.path.normpath(log_dir) + ', log directory not changed.']
sickbeard.USE_API = config.checkbox_to_value(use_api) sickbeard.USE_API = config.checkbox_to_value(use_api)
sickbeard.API_KEY = api_key sickbeard.API_KEY = api_key
sickbeard.WEB_PORT = config.to_int(web_port)
# sickbeard.WEB_LOG is set in config.change_LOG_DIR()
sickbeard.ENABLE_HTTPS = config.checkbox_to_value(enable_https) sickbeard.ENABLE_HTTPS = config.checkbox_to_value(enable_https)
if not config.change_HTTPS_CERT(https_cert): if not config.change_HTTPS_CERT(https_cert):
results += [ results += [
'Unable to create directory ' + os.path.normpath(https_cert) + ', https cert directory not changed.'] 'Unable to create directory ' + os.path.normpath(https_cert) + ', https cert directory not changed.']
if not config.change_HTTPS_KEY(https_key): if not config.change_HTTPS_KEY(https_key):
results += [ results += [
'Unable to create directory ' + os.path.normpath(https_key) + ', https key directory not changed.'] 'Unable to create directory ' + os.path.normpath(https_key) + ', https key directory not changed.']
sickbeard.WEB_IPV6 = config.checkbox_to_value(web_ipv6)
sickbeard.HANDLE_REVERSE_PROXY = config.checkbox_to_value(handle_reverse_proxy) sickbeard.HANDLE_REVERSE_PROXY = config.checkbox_to_value(handle_reverse_proxy)
sickbeard.THEME_NAME = theme_name # Advanced
sickbeard.DEFAULT_HOME = default_home sickbeard.GIT_REMOTE = git_remote
sickbeard.GIT_PATH = git_path
sickbeard.CPU_PRESET = cpu_preset
sickbeard.ANON_REDIRECT = anon_redirect
sickbeard.ENCRYPTION_VERSION = config.checkbox_to_value(encryption_version)
sickbeard.PROXY_SETTING = proxy_setting
sickbeard.PROXY_INDEXERS = config.checkbox_to_value(proxy_indexers)
sickbeard.FILE_LOGGING_PRESET = file_logging_preset
# sickbeard.LOG_DIR is set in config.change_LOG_DIR()
logger.log_set_level()
sickbeard.save_config() sickbeard.save_config()
if len(results) > 0: if 0 < len(results):
for v in results: for v in results:
logger.log(v, logger.ERROR) logger.log(v, logger.ERROR)
ui.notifications.error('Error(s) Saving Configuration', ui.notifications.error('Error(s) Saving Configuration',
@ -4496,7 +4719,7 @@ class ConfigGeneral(Config):
ui.notifications.message('Configuration Saved', ek.ek(os.path.join, sickbeard.CONFIG_FILE)) ui.notifications.message('Configuration Saved', ek.ek(os.path.join, sickbeard.CONFIG_FILE))
if reload_page: if reload_page:
self.clear_cookie('sickgear-session') self.clear_cookie('sickgear-session-%s' % helpers.md5_for_text(sickbeard.WEB_PORT))
self.write('reload') self.write('reload')
@staticmethod @staticmethod
@ -4994,6 +5217,7 @@ class ConfigProviders(Config):
cur_name, cur_url, cur_key, cur_cat = curNewznabProviderStr.split('|') cur_name, cur_url, cur_key, cur_cat = curNewznabProviderStr.split('|')
cur_url = config.clean_url(cur_url) cur_url = config.clean_url(cur_url)
cur_key = cur_key.strip()
if starify(cur_key, True): if starify(cur_key, True):
cur_key = '' cur_key = ''
@ -5552,8 +5776,10 @@ class UI(MainHandler):
class ErrorLogs(MainHandler): class ErrorLogs(MainHandler):
@staticmethod @staticmethod
def ErrorLogsMenu(): def ErrorLogsMenu():
if len(classes.ErrorViewer.errors):
return [{'title': 'Download Log', 'path': 'errorlogs/downloadlog/'}, return [{'title': 'Download Log', 'path': 'errorlogs/downloadlog/'},
{'title': 'Clear Errors', 'path': 'errorlogs/clearerrors/'},] {'title': 'Clear Errors', 'path': 'errorlogs/clearerrors/'},]
return [{'title': 'Download Log', 'path': 'errorlogs/downloadlog/'},]
def index(self, *args, **kwargs): def index(self, *args, **kwargs):
@ -5583,27 +5809,23 @@ class ErrorLogs(MainHandler):
except (StandardError, Exception): except (StandardError, Exception):
return return
def viewlog(self, minLevel=logger.MESSAGE, maxLines=500): def viewlog(self, min_level=logger.MESSAGE, max_lines=500):
t = PageTemplate(headers=self.request.headers, file='viewlogs.tmpl') t = PageTemplate(headers=self.request.headers, file='viewlogs.tmpl')
t.submenu = self.ErrorLogsMenu t.submenu = self.ErrorLogsMenu
minLevel = int(minLevel) min_level = int(min_level)
data = []
if os.path.isfile(logger.sb_log_instance.log_file_path):
with ek.ek(open, logger.sb_log_instance.log_file_path) as f:
data = f.readlines()
regex = '^(\d\d\d\d)\-(\d\d)\-(\d\d)\s*(\d\d)\:(\d\d):(\d\d)\s*([A-Z]+)\s*(.+?)\s*\:\:\s*(.*)$' regex = '^(\d\d\d\d)\-(\d\d)\-(\d\d)\s*(\d\d)\:(\d\d):(\d\d)\s*([A-Z]+)\s*(.+?)\s*\:\:\s*(.*)$'
finalData = [] final_data = []
normal_data = []
truncate = []
repeated = None
num_lines = 0
numLines = 0 if os.path.isfile(logger.sb_log_instance.log_file_path):
lastLine = False for x in logger.sb_log_instance.reverse_readline(logger.sb_log_instance.log_file_path):
numToShow = min(maxLines, len(data))
for x in reversed(data):
x = x.decode('utf-8', 'replace') x = x.decode('utf-8', 'replace')
match = re.match(regex, x) match = re.match(regex, x)
@ -5611,28 +5833,49 @@ class ErrorLogs(MainHandler):
if match: if match:
level = match.group(7) level = match.group(7)
if level not in logger.reverseNames: if level not in logger.reverseNames:
lastLine = False normal_data = []
continue continue
if logger.reverseNames[level] >= minLevel: if logger.reverseNames[level] >= min_level:
lastLine = True if truncate and not normal_data and truncate[0] == match.group(8) + match.group(9):
finalData.append(x) truncate += [match.group(8) + match.group(9)]
repeated = x
continue
if 1 < len(truncate):
final_data[-1] = repeated.strip() + \
' <span class="grey-text">(...%s repeat lines)</span>\n' % len(truncate)
truncate = [match.group(8) + match.group(9)]
final_data.append(x.replace(
' Starting SickGear', ' <span class="prelight2">Starting SickGear</span>'))
if any(normal_data):
final_data += ['<code><span class="prelight">'] + \
['<span class="prelight-num">%02s)</span> %s' % (n + 1, x)
for n, x in enumerate(normal_data[::-1])] + \
['</span></code><br />']
num_lines += len(normal_data)
normal_data = []
else: else:
lastLine = False normal_data = []
continue continue
elif lastLine: else:
finalData.append('AA' + x) if not any(normal_data) and not any([x.strip()]):
continue
numLines += 1 normal_data.append(re.sub(r'\r?\n', '<br />', x.replace('<', '&lt;').replace('>', '&gt;')))
if numLines >= numToShow: num_lines += 1
if num_lines >= max_lines:
break break
result = ''.join(finalData) result = ''.join(final_data)
t.logLines = result t.logLines = result
t.minLevel = minLevel t.min_level = min_level
return t.respond() return t.respond()