Merge pull request #708 from JackDandy/feature/AddFanArt
Add fanart to Episodes View, Display Show, and Edit Show page.
54
CHANGES.md
|
@ -201,6 +201,56 @@
|
|||
* Change sab API request to prevent naming mismatch
|
||||
* Change update rTorrent systems
|
||||
* 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]
|
||||
* Change send nzb data to NZBGet for Anizb instead of url
|
||||
|
@ -371,7 +421,7 @@
|
|||
* Fix post processing season pack folders
|
||||
* 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 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
|
||||
* Remove seed time display for Transmission in config/Torrent Search page because the torrent client doesn't support it
|
||||
* Add PreToMe torrent provider
|
||||
|
@ -559,7 +609,7 @@
|
|||
* 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 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
|
||||
* Fix post processing of anime with version tags
|
||||
* Change accept SD titles that contain audio quality
|
||||
|
|
|
@ -12,6 +12,7 @@ Libs with customisations...
|
|||
/lib/pynma/pynma.py
|
||||
/lib/requests/packages/urllib3/connectionpool.py
|
||||
/lib/requests/packages/urllib3/util/ssl_.py
|
||||
/lib/tmdb_api/tmdb_api.py
|
||||
/lib/tornado
|
||||
/lib/tvdb/tvdb_api.py
|
||||
/lib/tvdb_api/tvdb_api.py
|
||||
/lib/tzlocal/unix.py
|
||||
|
|
|
@ -1,6 +1,24 @@
|
|||
/* =======================================================================
|
||||
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-"]{
|
||||
|
@ -41,21 +59,21 @@ inc_top.tmpl
|
|||
.ui-widget-content{
|
||||
background:#606060;
|
||||
border:1px solid #111;
|
||||
color:#fff
|
||||
color:#ddd
|
||||
}
|
||||
|
||||
.ui-widget-content a{
|
||||
color:#2D8FBF
|
||||
color:#2d8fbf
|
||||
}
|
||||
|
||||
.ui-widget-content a:hover{
|
||||
color:#09A2FF
|
||||
color:#09a2ff
|
||||
}
|
||||
|
||||
.ui-widget-header{
|
||||
background:#3d3d3d;
|
||||
border:1px solid #111;
|
||||
color:#fff
|
||||
color:#ddd
|
||||
}
|
||||
|
||||
.ui-state-default,
|
||||
|
@ -103,7 +121,7 @@ inc_top.tmpl
|
|||
}
|
||||
|
||||
.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,
|
||||
|
@ -133,12 +151,12 @@ inc_top.tmpl
|
|||
}
|
||||
|
||||
.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited{
|
||||
color:#140F06;
|
||||
color:#140f06;
|
||||
text-decoration:none
|
||||
}
|
||||
|
||||
.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited{
|
||||
color:#fff;
|
||||
color:#ddd;
|
||||
text-decoration:none
|
||||
}
|
||||
|
||||
|
@ -180,13 +198,6 @@ inc_top.tmpl
|
|||
border-top-right-radius:5px
|
||||
}
|
||||
|
||||
#SubMenu{
|
||||
padding-right:20px;
|
||||
clear:both;
|
||||
font-size:12px;
|
||||
float:right
|
||||
}
|
||||
|
||||
.upgrade-notification{
|
||||
width:600px;
|
||||
text-align:center;
|
||||
|
@ -201,7 +212,7 @@ inc_bottom.tmpl
|
|||
========================================================================== */
|
||||
|
||||
.footerhighlight{
|
||||
color:#09A2FF
|
||||
color:#09a2ff
|
||||
}
|
||||
|
||||
/* =======================================================================
|
||||
|
@ -219,7 +230,7 @@ home.tmpl
|
|||
.ui-font,
|
||||
a.ui-font{
|
||||
text-shadow:0 0 0.1em #000;
|
||||
color:#fff
|
||||
color:#ddd
|
||||
}
|
||||
|
||||
#show-list .show-card{
|
||||
|
@ -265,14 +276,14 @@ a.ui-font{
|
|||
}
|
||||
|
||||
td.tvShow a{
|
||||
color:#fff;
|
||||
color:#ddd;
|
||||
text-decoration:none
|
||||
}
|
||||
|
||||
td.tvShow a:hover span,
|
||||
td.tvShow a:hover{
|
||||
cursor:pointer;
|
||||
color:#09A2FF
|
||||
color:#09a2ff
|
||||
}
|
||||
|
||||
/* =======================================================================
|
||||
|
@ -302,9 +313,8 @@ home_newShow.tmpl
|
|||
}
|
||||
|
||||
#addRootDirTable td label .filepath,
|
||||
.grey-text{
|
||||
color:#999
|
||||
}
|
||||
.grey-text{color:#999}
|
||||
.highlight-text{color:#fff}
|
||||
|
||||
#newShowPortal #displayText .show-name,
|
||||
#newShowPortal #displayText .show-dest,
|
||||
|
@ -314,7 +324,7 @@ home_newShow.tmpl
|
|||
|
||||
#newShowPortal #displayText .show-name,
|
||||
#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
|
||||
========================================================================== */
|
||||
body#display-show.back-art{
|
||||
color:#ddd
|
||||
}
|
||||
|
||||
tr.seasonheader{
|
||||
text-align:left;
|
||||
|
@ -355,51 +384,88 @@ tr.seasonheader{
|
|||
#prevShow,
|
||||
#nextShow,
|
||||
#topcontrol{
|
||||
-webkit-filter:"none";
|
||||
-webkit-filter:none;
|
||||
filter:none
|
||||
}
|
||||
|
||||
.tvshowImg{
|
||||
#posterCol .tvshowImg{
|
||||
border:1px solid #111
|
||||
}
|
||||
|
||||
.display-details{
|
||||
background-color:#3d3d3d;
|
||||
border:1px solid #111
|
||||
body#display-show.back-art .displayshow-wrapper .label a{
|
||||
color:#ddd
|
||||
}
|
||||
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{
|
||||
color:#999
|
||||
#edit-show.back-art .ui-tabs-nav > :not(.ui-tabs-active){
|
||||
background:rgba(0,0,0,0.2)
|
||||
}
|
||||
|
||||
.back-art.pro .details-title{
|
||||
color:#bbb
|
||||
#edit-show.back-art .ui-tabs-nav .ui-tabs-active,
|
||||
#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-bottom .label{
|
||||
background-color:#15528F
|
||||
background-color:#15528f
|
||||
}
|
||||
|
||||
#details-top .label,
|
||||
#details-bottom .label{
|
||||
background-color:#15528F
|
||||
background-color:#15528f
|
||||
}
|
||||
|
||||
.paused-highlight{
|
||||
color:#09A2FF
|
||||
color:#09a2ff
|
||||
}
|
||||
|
||||
.sickbeardTable th{
|
||||
background-color:#15528f
|
||||
}
|
||||
|
||||
.back-art th.row-seasonheader h3,
|
||||
.displayshow-wrapper .sickbeardTable th.row-seasonheader{
|
||||
color:#fff
|
||||
color:#ddd
|
||||
}
|
||||
|
||||
.back-art.pro .sickbeardTable .seasoncols th,
|
||||
.translucent.pro .sickbeardTable .seasoncols th{
|
||||
.back-art.pro.ii .navbar-default,
|
||||
.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)
|
||||
}
|
||||
|
||||
|
@ -408,19 +474,19 @@ episodeView.tmpl
|
|||
========================================================================== */
|
||||
|
||||
h2.day, h2.network{
|
||||
color:#FFF;
|
||||
color:#ddd;
|
||||
text-shadow:-1px -1px 0 rgba(0, 0, 0, 0.3);
|
||||
background-color:#15528F
|
||||
background-color:#15528f
|
||||
}
|
||||
|
||||
.tvshowDiv{
|
||||
border:1px solid #ccc;
|
||||
background:#fff;
|
||||
background:#ddd;
|
||||
color:#000
|
||||
}
|
||||
|
||||
.tvshowDiv a:hover{
|
||||
color:#09A2FF
|
||||
color:#09a2ff
|
||||
}
|
||||
|
||||
.tvshowTitle a{
|
||||
|
@ -450,12 +516,12 @@ h2.day, h2.network{
|
|||
|
||||
#showListTable td.tvShow a:hover{
|
||||
cursor:pointer;
|
||||
color:#09A2FF
|
||||
color:#09a2ff
|
||||
}
|
||||
|
||||
.day-of-week .day-number{
|
||||
background-color:#15528F;
|
||||
color:#fff
|
||||
background-color:#15528f;
|
||||
color:#ddd
|
||||
}
|
||||
|
||||
.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 .episode,
|
||||
.day-of-week .text .episode .name{
|
||||
color:#fff
|
||||
color:#ddd
|
||||
}
|
||||
|
||||
.day-of-week .text .episode .season,
|
||||
|
@ -506,14 +572,14 @@ h2.day, h2.network{
|
|||
}
|
||||
|
||||
.carousel-control{
|
||||
color:#297AB8;
|
||||
color:#297ab8;
|
||||
filter:alpha(opacity=100);
|
||||
opacity:1
|
||||
}
|
||||
|
||||
.carousel-control:hover,
|
||||
.carousel-control:focus{
|
||||
color:#15528F;
|
||||
color:#15528f;
|
||||
filter:alpha(opacity=100);
|
||||
opacity:1
|
||||
}
|
||||
|
@ -524,8 +590,8 @@ h2.day, h2.network{
|
|||
}
|
||||
|
||||
.carousel-indicators .active{
|
||||
background:#8DBEEE;
|
||||
border-color:#8DBEEE
|
||||
background:#8dbeee;
|
||||
border-color:#8dbeee
|
||||
}
|
||||
|
||||
/* =======================================================================
|
||||
|
@ -554,13 +620,16 @@ config*.tmpl
|
|||
}
|
||||
|
||||
.testNotification{
|
||||
border:1px dotted #CCC
|
||||
border:1px dotted #ccc
|
||||
}
|
||||
|
||||
#provider_order_list li,
|
||||
#service_order_list li{
|
||||
color:#ddd
|
||||
}
|
||||
|
||||
#service_order_list li{
|
||||
background:#333 !important;
|
||||
color:#fff
|
||||
}
|
||||
|
||||
.infoTableSeperator{
|
||||
|
@ -581,14 +650,23 @@ config_postProcessing.tmpl
|
|||
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{
|
||||
background-color:#3d3d3d;
|
||||
border:1px solid #111
|
||||
}
|
||||
|
||||
.Key th, .tableHeader{
|
||||
color:#fff;
|
||||
background:#15528F
|
||||
color:#ddd;
|
||||
background:#15528f
|
||||
}
|
||||
|
||||
.Key tr{
|
||||
|
@ -605,17 +683,17 @@ config_notifications.tmpl
|
|||
|
||||
div.metadata_options{
|
||||
background:#333;
|
||||
color:#fff;
|
||||
color:#ddd;
|
||||
border:1px solid #111
|
||||
}
|
||||
|
||||
div.metadata_options label:hover{
|
||||
color:#fff;
|
||||
background-color:#15528F
|
||||
color:#ddd;
|
||||
background-color:#15528f
|
||||
}
|
||||
|
||||
div.metadata_options label{
|
||||
color:#fff
|
||||
color:#ddd
|
||||
}
|
||||
|
||||
div.metadata_example{
|
||||
|
@ -623,7 +701,7 @@ div.metadata_example{
|
|||
}
|
||||
|
||||
div.metadata_example label{
|
||||
color:#fff
|
||||
color:#ddd
|
||||
}
|
||||
|
||||
div.metadataDiv .disabled{
|
||||
|
@ -631,8 +709,8 @@ div.metadataDiv .disabled{
|
|||
}
|
||||
|
||||
.warning{
|
||||
border-color:#F89406;
|
||||
background:url("../images/warning16.png") no-repeat right 5px center #fff
|
||||
border-color:#f89406;
|
||||
background:url("../images/warning16.png") no-repeat right 5px center #ddd
|
||||
}
|
||||
|
||||
.solid-border{
|
||||
|
@ -648,7 +726,7 @@ manage*.tmpl
|
|||
========================================================================== */
|
||||
|
||||
.separator{
|
||||
color:#fff
|
||||
color:#ddd
|
||||
}
|
||||
|
||||
a.whitelink{
|
||||
|
@ -660,7 +738,7 @@ a.whitelink{
|
|||
========================================================================== */
|
||||
|
||||
#error-404 path{
|
||||
fill:#fff
|
||||
fill:#ddd
|
||||
}
|
||||
|
||||
/* =======================================================================
|
||||
|
@ -668,7 +746,7 @@ Global
|
|||
========================================================================== */
|
||||
|
||||
span.path{
|
||||
color:#09A2FF;
|
||||
color:#09a2ff;
|
||||
background-color:#333
|
||||
}
|
||||
|
||||
|
@ -687,7 +765,7 @@ body{
|
|||
|
||||
body,
|
||||
.show-date{
|
||||
color:#fff
|
||||
color:#ddd
|
||||
}
|
||||
|
||||
input, textarea, select, .uneditable-input{
|
||||
|
@ -697,24 +775,24 @@ input, textarea, select, .uneditable-input{
|
|||
|
||||
/* navbar styling */
|
||||
.navbar-default{
|
||||
background-color:#15528F;
|
||||
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#297AB8', endColorstr='#15528F');
|
||||
background-image:-ms-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:-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:linear-gradient(to bottom, #297AB8 0%, #15528F 100%);
|
||||
background-color:#15528f;
|
||||
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#297ab8", endColorstr="#15528f");
|
||||
background-image:-ms-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:-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:linear-gradient(to bottom, #297ab8 0%, #15528f 100%);
|
||||
border-color:#3e3f3a
|
||||
}
|
||||
|
||||
.navbar-default .navbar-brand{
|
||||
color:#fff
|
||||
color:#ddd
|
||||
}
|
||||
|
||||
.navbar-default .navbar-brand:hover,
|
||||
.navbar-default .navbar-brand:focus{
|
||||
color:#fff;
|
||||
color:#ddd;
|
||||
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:focus{
|
||||
color:#fff;
|
||||
color:#ddd;
|
||||
background-color:#124477
|
||||
}
|
||||
|
||||
.navbar-default .navbar-nav > .active > a,
|
||||
.navbar-default .navbar-nav > .active > a:hover,
|
||||
.navbar-default .navbar-nav > .active > a:focus{
|
||||
color:#fff;
|
||||
color:#ddd;
|
||||
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:focus{
|
||||
background-color:#124477;
|
||||
color:#fff
|
||||
color:#ddd
|
||||
}
|
||||
|
||||
@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:focus{
|
||||
color:#fff;
|
||||
color:#ddd;
|
||||
background-color:transparent
|
||||
}
|
||||
.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:focus{
|
||||
color:#fff;
|
||||
color:#ddd;
|
||||
background-color:#124477
|
||||
}
|
||||
.navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,
|
||||
|
@ -799,7 +877,7 @@ input, textarea, select, .uneditable-input{
|
|||
}
|
||||
|
||||
.navbar-default .navbar-link:hover{
|
||||
color:#fff
|
||||
color:#ddd
|
||||
}
|
||||
|
||||
.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{
|
||||
color:#fff;
|
||||
color:#ddd;
|
||||
text-decoration:none;
|
||||
background-color:#15528F
|
||||
background-color:#15528f
|
||||
}
|
||||
|
||||
.dropdown-menu > li > a{
|
||||
color:#fff
|
||||
color:#ddd
|
||||
}
|
||||
|
||||
.dropdown-menu{
|
||||
|
@ -834,26 +912,29 @@ fieldset[disabled] .navbar-default .btn-link:focus{
|
|||
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{
|
||||
color:#000
|
||||
}
|
||||
|
||||
.btn{
|
||||
color:#fff;
|
||||
color:#ddd;
|
||||
text-shadow:0 1px 1px rgba(0, 0, 0, 0.75);
|
||||
background-color:#2672B6;
|
||||
*background-color:#2672B6;
|
||||
background-image:-ms-linear-gradient(top, #297AB8, #15528F);
|
||||
background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#297AB8), to(#15528F));
|
||||
background-image:-webkit-linear-gradient(top, #297AB8, #15528F);
|
||||
background-image:-o-linear-gradient(top, #297AB8, #15528F);
|
||||
background-image:linear-gradient(top, #297AB8, #15528F);
|
||||
background-image:-moz-linear-gradient(top, #297AB8, #15528F);
|
||||
background-color:#2672b6;
|
||||
*background-color:#2672b6;
|
||||
background-image:-ms-linear-gradient(top, #297ab8, #15528f);
|
||||
background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#297ab8), to(#15528f));
|
||||
background-image:-webkit-linear-gradient(top, #297ab8, #15528f);
|
||||
background-image:-o-linear-gradient(top, #297ab8, #15528f);
|
||||
background-image:linear-gradient(top, #297ab8, #15528f);
|
||||
background-image:-moz-linear-gradient(top, #297ab8, #15528f);
|
||||
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:#111 #111 #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);
|
||||
-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);
|
||||
|
@ -865,21 +946,21 @@ fieldset[disabled] .navbar-default .btn-link:focus{
|
|||
.btn.active,
|
||||
.btn.disabled,
|
||||
.btn[disabled]{
|
||||
background-color:#2672B6;
|
||||
*background-color:#2672B6;
|
||||
color:#fff
|
||||
background-color:#2672b6;
|
||||
*background-color:#2672b6;
|
||||
color:#ddd
|
||||
}
|
||||
|
||||
.btn:active,
|
||||
.btn.active{
|
||||
background-color:#ccc \9;
|
||||
color:#fff
|
||||
color:#ddd
|
||||
}
|
||||
|
||||
.btn:hover{
|
||||
color:#fff;
|
||||
background-color:#2672B6;
|
||||
*background-color:#2672B6;
|
||||
color:#ddd;
|
||||
background-color:#2672b6;
|
||||
*background-color:#2672b6;
|
||||
background-position:0 -150px;
|
||||
-webkit-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:5px auto -webkit-focus-ring-color;
|
||||
outline-offset:-2px;
|
||||
color:#fff
|
||||
color:#ddd
|
||||
}
|
||||
|
||||
.btn.active,
|
||||
.btn:active{
|
||||
background-color:#2672B6;
|
||||
background-color:#2672B6 \9;
|
||||
background-color:#2672b6;
|
||||
background-color:#2672b6 \9;
|
||||
background-image:none;
|
||||
color:#fff;
|
||||
color:#ddd;
|
||||
outline:0;
|
||||
-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);
|
||||
|
@ -910,7 +991,7 @@ fieldset[disabled] .navbar-default .btn-link:focus{
|
|||
.btn.disabled,
|
||||
.btn[disabled]{
|
||||
cursor:default;
|
||||
background:#15528F none;
|
||||
background:#15528f none;
|
||||
opacity:0.65;
|
||||
filter:alpha(opacity=65);
|
||||
-webkit-box-shadow:none;
|
||||
|
@ -940,13 +1021,15 @@ fieldset[disabled] .navbar-default .btn-link:focus{
|
|||
.btn-warning:hover,
|
||||
.btn-danger,
|
||||
.btn-danger:hover,
|
||||
.ui-widget-content .btn-danger,
|
||||
.ui-widget-content .btn-danger:hover,
|
||||
.btn-success,
|
||||
.btn-success:hover,
|
||||
.btn-info,
|
||||
.btn-info:hover,
|
||||
.btn-inverse,
|
||||
.btn-inverse:hover{
|
||||
color:#fff;
|
||||
color:#ddd;
|
||||
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;
|
||||
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);
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -1001,7 +1084,7 @@ fieldset[disabled] .navbar-default .btn-link:focus{
|
|||
background-repeat:repeat-x;
|
||||
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);
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -1031,7 +1114,7 @@ fieldset[disabled] .navbar-default .btn-link:focus{
|
|||
background-repeat:repeat-x;
|
||||
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);
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -1061,7 +1144,7 @@ fieldset[disabled] .navbar-default .btn-link:focus{
|
|||
background-repeat:repeat-x;
|
||||
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);
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -1091,7 +1174,7 @@ fieldset[disabled] .navbar-default .btn-link:focus{
|
|||
background-repeat:repeat-x;
|
||||
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);
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -1121,7 +1204,7 @@ fieldset[disabled] .navbar-default .btn-link:focus{
|
|||
background-repeat:repeat-x;
|
||||
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);
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -1160,9 +1243,9 @@ fieldset[disabled] .navbar-default .btn-link:focus{
|
|||
|
||||
.navbar-default .navbar-nav > .active > a{
|
||||
background-color:transparent;
|
||||
-webkit-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
|
||||
-webkit-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
|
||||
}
|
||||
|
||||
.navbar-fixed-top{
|
||||
|
@ -1171,7 +1254,7 @@ fieldset[disabled] .navbar-default .btn-link:focus{
|
|||
}
|
||||
|
||||
pre{
|
||||
color:#fff;
|
||||
color:#ddd;
|
||||
background-color:#3d3d3d;
|
||||
border-color:#111
|
||||
}
|
||||
|
@ -1193,7 +1276,7 @@ input sizing (for config pages)
|
|||
#showfilter optgroup option,
|
||||
#editAProvider optgroup option{
|
||||
color:#222;
|
||||
background-color:#fff
|
||||
background-color:#ddd
|
||||
}
|
||||
|
||||
/* =======================================================================
|
||||
|
@ -1206,7 +1289,7 @@ browser.css
|
|||
|
||||
#fileBrowserDialog ul li a:hover{
|
||||
color:#09a2ff;
|
||||
background: rgb(61, 61, 61) none
|
||||
background:rgb(61, 61, 61) none
|
||||
}
|
||||
|
||||
.ui-menu .ui-menu-item{
|
||||
|
@ -1214,11 +1297,11 @@ browser.css
|
|||
}
|
||||
|
||||
.ui-menu .ui-menu-item-alternate{
|
||||
background-color:#fff
|
||||
background-color:#ddd
|
||||
}
|
||||
|
||||
.ui-autocomplete .ui-menu-item .ui-state-focus{
|
||||
color:#fff;
|
||||
color:#ddd;
|
||||
background:none;
|
||||
background-color:#0a246a
|
||||
}
|
||||
|
@ -1229,11 +1312,11 @@ formWizard
|
|||
|
||||
.step,
|
||||
legend.legendStep{
|
||||
color:#fff
|
||||
color:#ddd
|
||||
}
|
||||
|
||||
div.stepsguide .step p{
|
||||
border-color:#23AFDC
|
||||
border-color:#23afdc
|
||||
}
|
||||
|
||||
.disabledstep{
|
||||
|
@ -1241,7 +1324,7 @@ div.stepsguide .step p{
|
|||
}
|
||||
|
||||
#newShowPortal #addShowForm .stepsguide .disabledstep:hover > .smalltext{
|
||||
color:#ccc;
|
||||
color:#ccc
|
||||
}
|
||||
|
||||
.stepDiv #searchResults div .exists-db{
|
||||
|
@ -1249,16 +1332,16 @@ div.stepsguide .step p{
|
|||
}
|
||||
|
||||
div.stepsguide .disabledstep p{
|
||||
border-color:#1178B3
|
||||
border-color:#1178b3
|
||||
}
|
||||
|
||||
div.formpaginate .prev, div.formpaginate .next{
|
||||
color:#fff;
|
||||
background:#2265A1
|
||||
color:#ddd;
|
||||
background:#2265a1
|
||||
}
|
||||
|
||||
#customQualityWrapper .tip-text p{
|
||||
color:#888
|
||||
color:#999
|
||||
}
|
||||
|
||||
/* =======================================================================
|
||||
|
@ -1276,11 +1359,11 @@ pnotify.css
|
|||
}
|
||||
|
||||
.ui-pnotify-title{
|
||||
color:#fff
|
||||
color:#ddd
|
||||
}
|
||||
|
||||
.ui-pnotify-text{
|
||||
color:#fff
|
||||
color:#ddd
|
||||
}
|
||||
|
||||
/* =======================================================================
|
||||
|
@ -1288,7 +1371,7 @@ tablesorter.css
|
|||
========================================================================== */
|
||||
|
||||
.tablesorter{
|
||||
color:#fff;
|
||||
color:#ddd;
|
||||
background-color:#333
|
||||
}
|
||||
|
||||
|
@ -1303,25 +1386,26 @@ tablesorter.css
|
|||
border-left:none
|
||||
}
|
||||
|
||||
.tablesorter th{
|
||||
color:#fff;
|
||||
.tablesorter th,
|
||||
.sickbeardTable thead .seasoncols td{
|
||||
color:#ddd;
|
||||
text-shadow:-1px -1px 0 rgba(0, 0, 0, 0.3);
|
||||
background-color:#15528F
|
||||
background-color:#15528f
|
||||
}
|
||||
|
||||
.tablesorter .tablesorter-header{
|
||||
background:#15528F url(data:image/gif;base64,R0lGODlhFQAJAIAAAP///////yH5BAEAAAEALAAAAAAVAAkAAAIXjI+AywnaYnhUMoqt3gZXPmVg94yJVQAAOw==) no-repeat center right;
|
||||
/* background-image:url(../images/tablesorter/bg.gif) */
|
||||
background:#15528f url("data:image/gif;base64,R0lGODlhFQAJAIAAAP///////yH5BAEAAAEALAAAAAAVAAkAAAIXjI+AywnaYnhUMoqt3gZXPmVg94yJVQAAOw==") no-repeat center right;
|
||||
/* background-image:url("../images/tablesorter/bg.gif") */
|
||||
}
|
||||
|
||||
.tablesorter thead .tablesorter-headerDesc{
|
||||
background:#297AB8 url(data:image/gif;base64,R0lGODlhFQAEAIAAAP///////yH5BAEAAAEALAAAAAAVAAQAAAINjB+gC+jP2ptn0WskLQA7) no-repeat center right;
|
||||
/* background-image:url(../images/tablesorter/asc.gif) */
|
||||
background:#297ab8 url("data:image/gif;base64,R0lGODlhFQAEAIAAAP///////yH5BAEAAAEALAAAAAAVAAQAAAINjB+gC+jP2ptn0WskLQA7") no-repeat center right;
|
||||
/* background-image:url("../images/tablesorter/asc.gif") */
|
||||
}
|
||||
|
||||
.tablesorter thead .tablesorter-headerAsc{
|
||||
background:#297AB8 url(data:image/gif;base64,R0lGODlhFQAEAIAAAP///////yH5BAEAAAEALAAAAAAVAAQAAAINjI8Bya2wnINUMopZAQA7) no-repeat center right;
|
||||
/* background-image:url(../images/tablesorter/desc.gif) */
|
||||
background:#297ab8 url("data:image/gif;base64,R0lGODlhFQAEAIAAAP///////yH5BAEAAAEALAAAAAAVAAQAAAINjI8Bya2wnINUMopZAQA7") no-repeat center right;
|
||||
/* background-image:url("../images/tablesorter/desc.gif") */
|
||||
}
|
||||
|
||||
thead.tablesorter-stickyHeader{
|
||||
|
@ -1329,11 +1413,16 @@ thead.tablesorter-stickyHeader{
|
|||
border-bottom:2px solid #222
|
||||
}
|
||||
|
||||
.ui-state-default.row-odd{
|
||||
background-color:#363636
|
||||
}
|
||||
|
||||
/* Zebra Widget - row alternating colors */
|
||||
.tablesorter tr.odd, .sickbeardTable tr.odd{
|
||||
background-color:#333
|
||||
}
|
||||
|
||||
.ui-state-default.row-even,
|
||||
.tablesorter tr.even, .sickbeardTable tr.even{
|
||||
background-color:#2e2e2e
|
||||
}
|
||||
|
@ -1346,7 +1435,7 @@ thead.tablesorter-stickyHeader{
|
|||
}
|
||||
|
||||
.tablesorter tfoot tr{
|
||||
color:#fff;
|
||||
color:#ddd;
|
||||
text-align:center;
|
||||
text-shadow:-1px -1px 0 rgba(0, 0, 0, 0.3);
|
||||
background-color:#333;
|
||||
|
@ -1354,7 +1443,7 @@ thead.tablesorter-stickyHeader{
|
|||
}
|
||||
|
||||
.tablesorter tfoot a{
|
||||
color:#fff
|
||||
color:#ddd
|
||||
}
|
||||
|
||||
#showListTable tbody{
|
||||
|
@ -1368,7 +1457,7 @@ token-input.css
|
|||
|
||||
ul.token-input-list{
|
||||
border:1px solid #ccc;
|
||||
background-color:#fff
|
||||
background-color:#ddd
|
||||
}
|
||||
|
||||
ul.token-input-list li input{
|
||||
|
@ -1387,7 +1476,7 @@ li.token-input-token span{
|
|||
|
||||
li.token-input-selected-token{
|
||||
background-color:#08844e;
|
||||
color:#fff
|
||||
color:#ddd
|
||||
}
|
||||
|
||||
li.token-input-selected-token span{
|
||||
|
@ -1395,7 +1484,7 @@ li.token-input-selected-token span{
|
|||
}
|
||||
|
||||
div.token-input-dropdown{
|
||||
background-color:#fff;
|
||||
background-color:#ddd;
|
||||
color:#000;
|
||||
border-left-color:#ccc;
|
||||
border-right-color:#ccc;
|
||||
|
@ -1407,7 +1496,7 @@ div.token-input-dropdown p{
|
|||
}
|
||||
|
||||
div.token-input-dropdown ul li{
|
||||
background-color:#fff
|
||||
background-color:#ddd
|
||||
}
|
||||
|
||||
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{
|
||||
background-color:#fff
|
||||
background-color:#ddd
|
||||
}
|
||||
|
||||
div.token-input-dropdown ul li.token-input-selected-dropdown-item{
|
||||
|
@ -1427,7 +1516,7 @@ jquery.confirm.css
|
|||
========================================================================== */
|
||||
|
||||
#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:-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
|
||||
|
@ -1440,19 +1529,19 @@ jquery.confirm.css
|
|||
}
|
||||
|
||||
#confirmBox h1{
|
||||
background-color:#15528F;
|
||||
background-color:#15528f;
|
||||
border-bottom:1px solid #111;
|
||||
color:#fff;
|
||||
color:#ddd;
|
||||
text-shadow:0 1px 1px rgba(0, 0, 0, 0.75)
|
||||
}
|
||||
|
||||
#confirmBox p{
|
||||
color:#fff;
|
||||
color:#ddd;
|
||||
text-shadow:0 1px 1px rgba(0, 0, 0, 0.75)
|
||||
}
|
||||
|
||||
#confirmBox .button{
|
||||
color:#fff;
|
||||
color:#ddd;
|
||||
text-shadow:0 1px 1px rgba(0, 0, 0, 0.75);
|
||||
border:1px solid #111;
|
||||
border-radius:3px;
|
||||
|
@ -1465,17 +1554,17 @@ jquery.confirm.css
|
|||
}
|
||||
|
||||
#confirmBox .green{
|
||||
background-color:#3F7636
|
||||
background-color:#3f7636
|
||||
}
|
||||
|
||||
#confirmBox .green:hover{
|
||||
background-color:#48873E
|
||||
background-color:#48873e
|
||||
}
|
||||
|
||||
#confirmBox .red{
|
||||
background-color:#8D2D2B
|
||||
background-color:#8d2d2b
|
||||
}
|
||||
|
||||
#confirmBox .red:hover{
|
||||
background-color:#A13331
|
||||
background-color:#a13331
|
||||
}
|
||||
|
|
BIN
gui/slick/css/fonts/Hack-Regular-mono.eot
Normal file
1543
gui/slick/css/fonts/Hack-Regular-mono.svg
Normal file
After Width: | Height: | Size: 3.4 MiB |
BIN
gui/slick/css/fonts/Hack-Regular-mono.ttf
Normal file
BIN
gui/slick/css/fonts/Hack-Regular-mono.woff
Normal file
Before Width: | Height: | Size: 191 KiB After Width: | Height: | Size: 205 KiB |
18
gui/slick/css/lib/jquery-ui-1.10.4.custom.css
vendored
|
@ -853,3 +853,21 @@ button.ui-button::-moz-focus-inner {
|
|||
filter: Alpha(Opacity=35);
|
||||
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)
|
||||
}
|
|
@ -1,14 +1,32 @@
|
|||
/* =======================================================================
|
||||
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-"]{
|
||||
background-image:url("../images/glyphicons-halflings.png")
|
||||
background-image:url("../images/glyphicons-halflings-white.png")
|
||||
}
|
||||
|
||||
.icon-white{
|
||||
background-image:url("../images/glyphicons-halflings-white.png")
|
||||
background-image:url("../images/glyphicons-halflings.png")
|
||||
}
|
||||
|
||||
.ui-autocomplete-loading{
|
||||
|
@ -43,7 +61,7 @@ inc_top.tmpl
|
|||
}
|
||||
|
||||
.ui-widget-content a:hover{
|
||||
color:#09A2FF
|
||||
color:#09a2ff
|
||||
}
|
||||
|
||||
.ui-widget-header{
|
||||
|
@ -54,7 +72,7 @@ inc_top.tmpl
|
|||
.ui-widget-content .ui-state-default,
|
||||
.ui-widget-header .ui-state-default{
|
||||
background:#fff;
|
||||
border:1px solid #CCC
|
||||
border:1px solid #ccc
|
||||
}
|
||||
|
||||
.ui-state-hover,
|
||||
|
@ -69,7 +87,7 @@ inc_top.tmpl
|
|||
.ui-state-active,
|
||||
.ui-widget-content .ui-state-active,
|
||||
.ui-widget-header .ui-state-active{
|
||||
background:#F7F7F7
|
||||
background:#f7f7f7
|
||||
}
|
||||
|
||||
.ui-state-highlight,
|
||||
|
@ -124,7 +142,7 @@ inc_top.tmpl
|
|||
}
|
||||
|
||||
.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited{
|
||||
color:#140F06;
|
||||
color:#140f06;
|
||||
text-decoration:none
|
||||
}
|
||||
|
||||
|
@ -149,8 +167,8 @@ inc_top.tmpl
|
|||
}
|
||||
|
||||
.ui-tabs .ui-tabs-panel{
|
||||
background-color:#F7F7F7 !important;
|
||||
border:1px solid #CCC !important
|
||||
background-color:#f7f7f7 !important;
|
||||
border:1px solid #ccc !important
|
||||
}
|
||||
|
||||
.ui-tabs .ui-tabs-nav li.ui-tabs-active{
|
||||
|
@ -184,19 +202,30 @@ inc_bottom.tmpl
|
|||
========================================================================== */
|
||||
|
||||
.footerhighlight{
|
||||
color:#428BCA
|
||||
color:#428bca
|
||||
}
|
||||
|
||||
body#display-show.back-art .displayshow-wrapper a,
|
||||
body#display-show.back-art .footerhighlight a,
|
||||
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:focus,
|
||||
body#display-show.back-art .footerhighlight a:hover,
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -219,7 +248,7 @@ a.ui-font{
|
|||
}
|
||||
|
||||
#show-list .show-card{
|
||||
background-color:#DFDACF;
|
||||
background-color:#dfdacf;
|
||||
color:#666;
|
||||
border:1px solid #111
|
||||
}
|
||||
|
@ -269,7 +298,7 @@ td.tvShow a{
|
|||
td.tvShow a:hover span,
|
||||
td.tvShow a:hover{
|
||||
cursor:pointer;
|
||||
color:#428BCA
|
||||
color:#428bca
|
||||
}
|
||||
|
||||
/* =======================================================================
|
||||
|
@ -299,9 +328,8 @@ home_newShow.tmpl
|
|||
}
|
||||
|
||||
#addRootDirTable td label .filepath,
|
||||
.grey-text{
|
||||
color:#666
|
||||
}
|
||||
.grey-text{color:#666}
|
||||
.highlight-text{color:#000}
|
||||
|
||||
#newShowPortal #displayText .show-name,
|
||||
#newShowPortal #displayText .show-dest,
|
||||
|
@ -319,7 +347,7 @@ home_addExistingShow.tmpl
|
|||
========================================================================== */
|
||||
|
||||
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{
|
||||
background-color:#DFDACF;
|
||||
background-color:#dfdacf;
|
||||
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
|
||||
========================================================================== */
|
||||
|
@ -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")
|
||||
}
|
||||
|
||||
.tvshowImg{
|
||||
border:1px solid #ccc
|
||||
#posterCol .tvshowImg{
|
||||
border: 1px solid rgba(239, 239, 239, 0.8);
|
||||
}
|
||||
|
||||
.display-details{
|
||||
background-color:#efefef;
|
||||
border:1px solid #dfdede
|
||||
#edit-show.back-art .ui-tabs-nav > :not(.ui-tabs-active){
|
||||
background:rgba(239, 239, 239,0.4)
|
||||
}
|
||||
|
||||
.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
|
||||
}
|
||||
|
||||
.back-art.pro .details-title{
|
||||
color:#bbb
|
||||
}
|
||||
|
||||
.back-art #details-top .label,
|
||||
.back-art #details-bottom .label{
|
||||
background-color:#215f2f
|
||||
|
@ -386,19 +447,24 @@ tr.seasonheader{
|
|||
}
|
||||
|
||||
.paused-highlight{
|
||||
color:#C7DB40
|
||||
color:#c7db40
|
||||
}
|
||||
|
||||
.sickbeardTable th{
|
||||
background-color:#333
|
||||
}
|
||||
|
||||
body#display-show.back-art,
|
||||
.displayshow-wrapper .sickbeardTable th.row-seasonheader{
|
||||
color:#000
|
||||
}
|
||||
|
||||
.translucent.pro .sickbeardTable th{
|
||||
background-color:rgba(51, 51, 51, 0.5)
|
||||
.back-art.pro.ii .navbar-default,
|
||||
.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{
|
||||
color:#FFF;
|
||||
color:#fff;
|
||||
text-shadow:-1px -1px 0 rgba(0, 0, 0, 0.3);
|
||||
background-color:#333
|
||||
}
|
||||
|
@ -417,7 +483,7 @@ h2.day, h2.network{
|
|||
}
|
||||
|
||||
.tvshowDiv a:hover{
|
||||
color:#428BCA
|
||||
color:#428bca
|
||||
}
|
||||
|
||||
.tvshowTitle a{
|
||||
|
@ -451,15 +517,15 @@ h2.day, h2.network{
|
|||
}
|
||||
|
||||
.odd .daybyday-show{
|
||||
background-color:#F5F1E4
|
||||
background-color:#f5f1e4
|
||||
}
|
||||
|
||||
.even .daybyday-show{
|
||||
background-color:#DFDACF
|
||||
background-color:#dfdacf
|
||||
}
|
||||
|
||||
.day-of-week .poster img{
|
||||
border-color:#CCC
|
||||
border-color:#ccc
|
||||
}
|
||||
|
||||
.over-layer0{
|
||||
|
@ -484,13 +550,25 @@ h2.day, h2.network{
|
|||
|
||||
.day-of-week .text .episode .season,
|
||||
.day-of-week .text .episode .number{
|
||||
color:rgb(9, 133, 225)
|
||||
color:#0985e1
|
||||
}
|
||||
|
||||
.day-of-week .text .episode{
|
||||
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-am-pm{
|
||||
color:#666
|
||||
|
@ -502,8 +580,8 @@ h2.day, h2.network{
|
|||
}
|
||||
|
||||
.carousel-indicators .active{
|
||||
background:#C7DB40;
|
||||
border-color:#C7DB40
|
||||
background:#c7db40;
|
||||
border-color:#c7db40
|
||||
}
|
||||
|
||||
/* =======================================================================
|
||||
|
@ -532,7 +610,7 @@ config*.tmpl
|
|||
}
|
||||
|
||||
.testNotification{
|
||||
border:1px dotted #CCC
|
||||
border:1px dotted #ccc
|
||||
}
|
||||
|
||||
.infoTableSeperator{
|
||||
|
@ -553,6 +631,16 @@ config_postProcessing.tmpl
|
|||
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{
|
||||
background-color:#f4f4f4;
|
||||
border:1px solid #ccc
|
||||
|
@ -602,7 +690,7 @@ div.metadataDiv .disabled{
|
|||
}
|
||||
|
||||
.warning{
|
||||
border-color:#F89406;
|
||||
border-color:#f89406;
|
||||
background:url("../images/warning16.png") no-repeat right 5px center #fff
|
||||
}
|
||||
|
||||
|
@ -665,7 +753,7 @@ input, textarea, select, .uneditable-input{
|
|||
/* navbar styling */
|
||||
.navbar-default{
|
||||
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:-moz-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{
|
||||
background-color:#F5F1E4;
|
||||
background-color:#f5f1e4;
|
||||
border:1px solid rgba(0, 0, 0, 0.15);
|
||||
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:#e6e6e6 #e6e6e6 #bfbfbf;
|
||||
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);
|
||||
-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);
|
||||
|
@ -899,6 +987,8 @@ fieldset[disabled] .navbar-default .btn-link:focus{
|
|||
.btn-warning:hover,
|
||||
.btn-danger,
|
||||
.btn-danger:hover,
|
||||
.ui-widget-content .btn-danger,
|
||||
.ui-widget-content .btn-danger:hover,
|
||||
.btn-success,
|
||||
.btn-success:hover,
|
||||
.btn-info,
|
||||
|
@ -930,7 +1020,7 @@ fieldset[disabled] .navbar-default .btn-link:focus{
|
|||
background-repeat:repeat-x;
|
||||
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);
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -960,7 +1050,7 @@ fieldset[disabled] .navbar-default .btn-link:focus{
|
|||
background-repeat:repeat-x;
|
||||
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);
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -990,7 +1080,7 @@ fieldset[disabled] .navbar-default .btn-link:focus{
|
|||
background-repeat:repeat-x;
|
||||
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);
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -1020,7 +1110,7 @@ fieldset[disabled] .navbar-default .btn-link:focus{
|
|||
background-repeat:repeat-x;
|
||||
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);
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -1050,7 +1140,7 @@ fieldset[disabled] .navbar-default .btn-link:focus{
|
|||
background-repeat:repeat-x;
|
||||
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);
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -1080,7 +1170,7 @@ fieldset[disabled] .navbar-default .btn-link:focus{
|
|||
background-repeat:repeat-x;
|
||||
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);
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -1112,16 +1202,16 @@ fieldset[disabled] .navbar-default .btn-link:focus{
|
|||
right:12px;
|
||||
display:inline-block;
|
||||
border-right:6px solid transparent;
|
||||
border-bottom:6px solid #F5F1E4;
|
||||
border-bottom:6px solid #f5f1e4;
|
||||
border-left:6px solid transparent;
|
||||
content:""
|
||||
}
|
||||
|
||||
.navbar-default .navbar-nav > .active > a{
|
||||
background-color:transparent;
|
||||
-webkit-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
|
||||
-webkit-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
|
||||
}
|
||||
|
||||
.navbar-fixed-top{
|
||||
|
@ -1131,7 +1221,7 @@ fieldset[disabled] .navbar-default .btn-link:focus{
|
|||
|
||||
pre{
|
||||
color:#000;
|
||||
background-color:#F5F5F5;
|
||||
background-color:#f5f5f5;
|
||||
border-color:#ccc
|
||||
}
|
||||
|
||||
|
@ -1161,7 +1251,7 @@ browser.css
|
|||
|
||||
#fileBrowserDialog ul li a:hover{
|
||||
color:#00f;
|
||||
background: rgb(220, 220, 220) none
|
||||
background:rgb(220, 220, 220) none
|
||||
}
|
||||
|
||||
.ui-menu .ui-menu-item{
|
||||
|
@ -1200,7 +1290,7 @@ div.stepsguide .disabledstep p{
|
|||
}
|
||||
|
||||
#newShowPortal #addShowForm .stepsguide .disabledstep:hover > .smalltext{
|
||||
color:#8a775e;
|
||||
color:#8a775e
|
||||
}
|
||||
|
||||
.stepDiv #searchResults div .exists-db{
|
||||
|
@ -1243,18 +1333,18 @@ tablesorter.css
|
|||
}
|
||||
|
||||
.tablesorter .tablesorter-header{
|
||||
background:#333 url(data:image/gif;base64,R0lGODlhFQAJAIAAAP///////yH5BAEAAAEALAAAAAAVAAkAAAIXjI+AywnaYnhUMoqt3gZXPmVg94yJVQAAOw==) no-repeat center right;
|
||||
/* background-image:url(../images/tablesorter/bg.gif) */
|
||||
background:#333 url("data:image/gif;base64,R0lGODlhFQAJAIAAAP///////yH5BAEAAAEALAAAAAAVAAkAAAIXjI+AywnaYnhUMoqt3gZXPmVg94yJVQAAOw==") no-repeat center right;
|
||||
/* background-image:url("../images/tablesorter/bg.gif" */
|
||||
}
|
||||
|
||||
.tablesorter thead .tablesorter-headerDesc{
|
||||
background:#555 url(data:image/gif;base64,R0lGODlhFQAEAIAAAP///////yH5BAEAAAEALAAAAAAVAAQAAAINjB+gC+jP2ptn0WskLQA7) no-repeat center right;
|
||||
/* background-image:url(../images/tablesorter/asc.gif) */
|
||||
background:#555 url("data:image/gif;base64,R0lGODlhFQAEAIAAAP///////yH5BAEAAAEALAAAAAAVAAQAAAINjB+gC+jP2ptn0WskLQA7") no-repeat center right;
|
||||
/* background-image:url("../images/tablesorter/asc.gif" */
|
||||
}
|
||||
|
||||
.tablesorter thead .tablesorter-headerAsc{
|
||||
background:#555 url(data:image/gif;base64,R0lGODlhFQAEAIAAAP///////yH5BAEAAAEALAAAAAAVAAQAAAINjI8Bya2wnINUMopZAQA7) no-repeat center right;
|
||||
/* background-image:url(../images/tablesorter/desc.gif) */
|
||||
background:#555 url("data:image/gif;base64,R0lGODlhFQAEAIAAAP///////yH5BAEAAAEALAAAAAAVAAQAAAINjI8Bya2wnINUMopZAQA7") no-repeat center right;
|
||||
/* background-image:url("../images/tablesorter/desc.gif" */
|
||||
}
|
||||
|
||||
thead.tablesorter-stickyHeader{
|
||||
|
@ -1263,10 +1353,12 @@ thead.tablesorter-stickyHeader{
|
|||
}
|
||||
|
||||
/* Zebra Widget - row alternating colors */
|
||||
.ui-state-default.row-odd,
|
||||
.tablesorter tr.odd, .sickbeardTable tr.odd{
|
||||
background-color:#f5f1e4
|
||||
}
|
||||
|
||||
.ui-state-default.row-even,
|
||||
.tablesorter tr.even, .sickbeardTable tr.even{
|
||||
background-color:#dfdacf
|
||||
}
|
||||
|
@ -1355,14 +1447,14 @@ jquery.confirm.css
|
|||
========================================================================== */
|
||||
|
||||
#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:-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
|
||||
}
|
||||
|
||||
#confirmBox{
|
||||
background:#F5F1E4;
|
||||
background:#f5f1e4;
|
||||
border:1px solid #111;
|
||||
box-shadow:0 0 12px 0 rgba(0, 0, 0, 0.175)
|
||||
}
|
||||
|
@ -1392,17 +1484,17 @@ jquery.confirm.css
|
|||
}
|
||||
|
||||
#confirmBox .green{
|
||||
background-color:#3F7636
|
||||
background-color:#3f7636
|
||||
}
|
||||
|
||||
#confirmBox .green:hover{
|
||||
background-color:#48873E
|
||||
background-color:#48873e
|
||||
}
|
||||
|
||||
#confirmBox .red{
|
||||
background-color:#8D2D2B
|
||||
background-color:#8d2d2b
|
||||
}
|
||||
|
||||
#confirmBox .red:hover{
|
||||
background-color:#A13331
|
||||
background-color:#a13331
|
||||
}
|
||||
|
|
BIN
gui/slick/images/addshows/add-existing16-black.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
gui/slick/images/addshows/add-existing16-white.png
Normal file
After Width: | Height: | Size: 306 B |
BIN
gui/slick/images/addshows/anime16.png
Normal file
After Width: | Height: | Size: 691 B |
BIN
gui/slick/images/addshows/imdb16.png
Normal file
After Width: | Height: | Size: 250 B |
BIN
gui/slick/images/addshows/trakt16-black.png
Normal file
After Width: | Height: | Size: 477 B |
BIN
gui/slick/images/addshows/trakt16-white.png
Normal file
After Width: | Height: | Size: 496 B |
BIN
gui/slick/images/arrows2.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
gui/slick/images/banner_thumb.jpg
Normal file
After Width: | Height: | Size: 7.3 KiB |
Before Width: | Height: | Size: 436 B After Width: | Height: | Size: 531 B |
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 1.2 KiB |
BIN
gui/slick/images/poster_thumb.jpg
Normal file
After Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 263 B After Width: | Height: | Size: 693 B |
|
@ -2,12 +2,14 @@
|
|||
#from sickbeard import db
|
||||
#from sickbeard.helpers import anon_url
|
||||
#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 $header = 'Configuration'
|
||||
#set global $sbPath = '..'
|
||||
#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')
|
||||
<h1 class='header'>$header</h1>
|
||||
|
@ -20,23 +22,25 @@
|
|||
<tr>
|
||||
<td class="infoTableHeader">Version: </td>
|
||||
<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 />
|
||||
#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.
|
||||
#end if
|
||||
</td>
|
||||
</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">Cache Dir:</td><td class="infoTableCell">$sickbeard.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">Web Root:</td><td class="infoTableCell">$sickbeard.WEB_ROOT</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">#echo $sg_var('MY_ARGS') or 'None used'#</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 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-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"> </td><td class="infoTableHeader">This project uses the TMDb API but is not endorsed or certified by TMDb.</td></tr>
|
||||
</table>
|
||||
</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')
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#from sickbeard.helpers import anon_url
|
||||
#from sickbeard.logger import reverseNames as file_logging_presets
|
||||
#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 $header = 'General Configuration'
|
||||
|
@ -17,7 +19,7 @@
|
|||
#set global $topmenu = 'config'
|
||||
##
|
||||
#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')
|
||||
<h1 class="header">$header</h1>
|
||||
|
@ -29,8 +31,8 @@
|
|||
#set $selected = ' selected="selected"'
|
||||
##
|
||||
#set $indexer = 0
|
||||
#if $sickbeard.INDEXER_DEFAULT
|
||||
#set $indexer = $sickbeard.INDEXER_DEFAULT
|
||||
#if $sg_var('INDEXER_DEFAULT')
|
||||
#set $indexer = $sg_var('INDEXER_DEFAULT')
|
||||
#end if
|
||||
|
||||
<script type="text/javascript" src="$sbRoot/js/config.js?v=$sbPID"></script>
|
||||
|
@ -62,7 +64,7 @@
|
|||
<label for="launch_browser">
|
||||
<span class="component-title">Launch browser</span>
|
||||
<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>
|
||||
</span>
|
||||
</label>
|
||||
|
@ -72,8 +74,8 @@
|
|||
<label for="update_shows_on_start">
|
||||
<span class="component-title">Update shows on startup</span>
|
||||
<span class="component-desc">
|
||||
<input type="checkbox" name="update_shows_on_start" id="update_shows_on_start"#echo ('', $checked)[$sickbeard.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>
|
||||
<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">$sg_var('SHOW_UPDATE_HOUR', 3)</span></p>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
|
@ -82,7 +84,7 @@
|
|||
<label for="show_update_hour">
|
||||
<span class="component-title">Update shows during hour</span>
|
||||
<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>
|
||||
</span>
|
||||
</label>
|
||||
|
@ -92,11 +94,11 @@
|
|||
<span class="component-title">Send to trash for actions</span>
|
||||
<span class="component-desc">
|
||||
<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>
|
||||
</label>
|
||||
<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>
|
||||
</label>
|
||||
<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">
|
||||
<span class="component-title">Log file folder location</span>
|
||||
<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>
|
||||
</label>
|
||||
</div>
|
||||
|
@ -119,7 +121,7 @@
|
|||
<select id="indexer_default" name="indexer_default" class="form-control input-sm">
|
||||
<option value="0"#echo ('', $selected)[0 == $indexer]#>All Indexers</option>
|
||||
#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
|
||||
</select>
|
||||
<span>as the default selection when adding new shows</span>
|
||||
|
@ -131,7 +133,7 @@
|
|||
<label for="indexer_timeout">
|
||||
<span class="component-title">Timeout show indexer at</span>
|
||||
<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>
|
||||
</span>
|
||||
</label>
|
||||
|
@ -142,7 +144,7 @@
|
|||
<span class="component-title">Show root directories</span>
|
||||
<span class="component-desc">
|
||||
<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>
|
||||
</label>
|
||||
</div>
|
||||
|
@ -162,7 +164,7 @@
|
|||
<label for="version_notify">
|
||||
<span class="component-title">Check software updates</span>
|
||||
<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.
|
||||
Checks are run on startup and at the frequency set below*</p>
|
||||
</span>
|
||||
|
@ -173,7 +175,7 @@
|
|||
<label for="auto_update">
|
||||
<span class="component-title">Automatically update</span>
|
||||
<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.
|
||||
Updates are run on startup and in the background at the frequency set below<sup>1</sup></p>
|
||||
</span>
|
||||
|
@ -184,7 +186,7 @@
|
|||
<label>
|
||||
<span class="component-title">Check the server every<sup>1</sup></span>
|
||||
<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>
|
||||
</span>
|
||||
</label>
|
||||
|
@ -194,7 +196,7 @@
|
|||
<label for="notify_on_update">
|
||||
<span class="component-title">Notify on software update</span>
|
||||
<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>
|
||||
</span>
|
||||
</label>
|
||||
|
@ -222,8 +224,8 @@
|
|||
<span class="component-title">Display theme:</span>
|
||||
<span class="component-desc">
|
||||
<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="light"#echo ('', $selected)['light' == $sickbeard.THEME_NAME]#>Light</option>
|
||||
<option value="dark"#echo ('', $selected)['dark' == $sg_str('THEME_NAME', 'dark')]#>Dark</option>
|
||||
<option value="light"#echo ('', $selected)['light' == $sg_str('THEME_NAME')]#>Light</option>
|
||||
</select>
|
||||
<span class="red-text">for appearance to take effect, save then refresh your browser</span>
|
||||
</span>
|
||||
|
@ -235,32 +237,43 @@
|
|||
<span class="component-title">Use as default home page:</span>
|
||||
<span class="component-desc">
|
||||
<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="episodes"#echo ('', $selected)['episodes' == $sickbeard.DEFAULT_HOME]#>Episodes</option>
|
||||
<option value="history"#echo ('', $selected)['history' == $sickbeard.DEFAULT_HOME]#>History</option>
|
||||
<option value="shows"#echo ('', $selected)['shows' == $sg_str('DEFAULT_HOME')]#>Shows</option>
|
||||
<option value="episodes"#echo ('', $selected)['episodes' == $sg_str('DEFAULT_HOME')]#>Episodes</option>
|
||||
<option value="history"#echo ('', $selected)['history' == $sg_str('DEFAULT_HOME')]#>History</option>
|
||||
</select>
|
||||
</span>
|
||||
</label>
|
||||
</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">
|
||||
<label for="showlist_tagview">
|
||||
<span class="component-title">Group show list shows into:</span>
|
||||
<span class="component-desc">
|
||||
<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="anime"#echo ('', $selected)['anime' == $sickbeard.SHOWLIST_TAGVIEW]#>Show / Anime Lists</option>
|
||||
<option value="custom"#echo ('', $selected)['custom' == $sickbeard.SHOWLIST_TAGVIEW]#>Custom Lists</option>
|
||||
<option value="standard"#echo ('', $selected)['standard' == $sg_str('SHOWLIST_TAGVIEW', 'standard')]#>One Show List</option>
|
||||
<option value="anime"#echo ('', $selected)['anime' == $sg_str('SHOWLIST_TAGVIEW')]#>Show / Anime Lists</option>
|
||||
<option value="custom"#echo ('', $selected)['custom' == $sg_str('SHOWLIST_TAGVIEW')]#>Custom Lists</option>
|
||||
</select>
|
||||
#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_anime"#echo ('', $hidden)['anime' not in $sickbeard.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_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 $sg_str('SHOWLIST_TAGVIEW')]#>two groups, the show list and anime</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>
|
||||
</label>
|
||||
</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">
|
||||
<span class="component-title">Group names for show list<sup>1</sup></span>
|
||||
<span class="component-desc">
|
||||
|
@ -275,7 +288,7 @@
|
|||
<label for="home_search_focus">
|
||||
<span class="component-title">Give show list search focus</span>
|
||||
<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>
|
||||
</span>
|
||||
</label>
|
||||
|
@ -285,7 +298,7 @@
|
|||
<label for="use_imdb_info">
|
||||
<span class="component-title">Enable IMDb info</span>
|
||||
<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>
|
||||
</span>
|
||||
</label>
|
||||
|
@ -298,7 +311,7 @@
|
|||
<span class="component-desc">
|
||||
<select id="imdb-accounts" class="pull-left form-control input-sm">
|
||||
<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
|
||||
#set $id = $v
|
||||
#else
|
||||
|
@ -326,7 +339,7 @@
|
|||
<label for="sort_article">
|
||||
<span class="component-title">Sort with "The", "A", "An"</span>
|
||||
<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>
|
||||
</span>
|
||||
</label>
|
||||
|
@ -340,16 +353,16 @@
|
|||
<label for="fuzzy_dating">
|
||||
<span class="component-title">Display fuzzy dates</span>
|
||||
<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>
|
||||
</span>
|
||||
</label>
|
||||
</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">
|
||||
<span class="component-title">Trim date and time</span>
|
||||
<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>
|
||||
</span>
|
||||
</label>
|
||||
|
@ -359,16 +372,16 @@
|
|||
<label for="date_presets">
|
||||
<span class="component-title">Date style:</span>
|
||||
<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
|
||||
<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
|
||||
</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]#">
|
||||
<option value="%x"#echo ('', $selected)['%x' == $sickbeard.DATE_PRESET]#>Use System Default</option>
|
||||
<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' == $sg_str('DATE_PRESET', '%x')]#>Use System Default</option>
|
||||
#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
|
||||
</select>
|
||||
</span>
|
||||
|
@ -381,8 +394,8 @@
|
|||
<span class="component-desc">
|
||||
<select id="time_presets" name="time_preset" class="form-control input-sm">
|
||||
#for $cur_preset in $time_presets
|
||||
#set $show_seconds = not $sickbeard.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>
|
||||
#set $show_seconds = not $sg_var('FUZZY_DATING')
|
||||
<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
|
||||
</select>
|
||||
<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-desc">
|
||||
<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 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>
|
||||
<div class="clear-left"><p>display dates and times in either your timezone or the shows network timezone</p></div>
|
||||
</span>
|
||||
|
@ -423,7 +436,7 @@
|
|||
<label for="web_username">
|
||||
<span class="component-title">Username</span>
|
||||
<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>
|
||||
</span>
|
||||
</label>
|
||||
|
@ -433,7 +446,7 @@
|
|||
<label for="web_password">
|
||||
<span class="component-title">Password</span>
|
||||
<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>
|
||||
<span class="clear-left">check autoProcessTV.cfg is set up for external apps to use post processing scripts</span>
|
||||
</span>
|
||||
|
@ -444,7 +457,7 @@
|
|||
<label for="calendar_unprotected">
|
||||
<span class="component-title">Unprotected calendar</span>
|
||||
<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.
|
||||
Some services like Google Calendar will only work with <b class="boldest">no</b> authentication</p>
|
||||
</span>
|
||||
|
@ -456,7 +469,7 @@
|
|||
<label for="use_api">
|
||||
<span class="component-title">API enable</span>
|
||||
<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>
|
||||
</span>
|
||||
</label>
|
||||
|
@ -466,7 +479,7 @@
|
|||
<label for="api_key">
|
||||
<span class="component-title">API key</span>
|
||||
<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">
|
||||
<div class="clear-left"><p>used to give 3rd party programs limited access to SickGear</p></div>
|
||||
</span>
|
||||
|
@ -478,7 +491,7 @@
|
|||
<label for="web_port">
|
||||
<span class="component-title">HTTP port</span>
|
||||
<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>
|
||||
</span>
|
||||
</label>
|
||||
|
@ -488,7 +501,7 @@
|
|||
<label for="web_log">
|
||||
<span class="component-title">HTTP logs</span>
|
||||
<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>
|
||||
</span>
|
||||
</label>
|
||||
|
@ -498,7 +511,7 @@
|
|||
<label for="enable_https">
|
||||
<span class="component-title">SSL enable</span>
|
||||
<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>
|
||||
</span>
|
||||
</label>
|
||||
|
@ -508,7 +521,7 @@
|
|||
<label for="https_cert">
|
||||
<span class="component-title">HTTPS certificate</span>
|
||||
<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>
|
||||
</span>
|
||||
</label>
|
||||
|
@ -517,7 +530,7 @@
|
|||
<label for="https_key">
|
||||
<span class="component-title">HTTPS key</span>
|
||||
<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>
|
||||
</span>
|
||||
</label>
|
||||
|
@ -528,7 +541,7 @@
|
|||
<label for="web_ipv6">
|
||||
<span class="component-title">Listen on IPv6</span>
|
||||
<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>
|
||||
</span>
|
||||
</label>
|
||||
|
@ -538,7 +551,7 @@
|
|||
<label for="handle_reverse_proxy">
|
||||
<span class="component-title">Reverse proxy headers</span>
|
||||
<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>
|
||||
</span>
|
||||
</label>
|
||||
|
@ -574,7 +587,7 @@
|
|||
</label>
|
||||
</div>
|
||||
|
||||
#if $sickbeard.BRANCH != 'master'
|
||||
#if $sg_str('BRANCH', 'master') != 'master'
|
||||
<div class="field-pair">
|
||||
<label>
|
||||
<span class="component-title">Pull request:</span>
|
||||
|
@ -593,7 +606,7 @@
|
|||
<label for="git_remote">
|
||||
<span class="component-title">Git remote for branch</span>
|
||||
<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>
|
||||
</span>
|
||||
</label>
|
||||
|
@ -603,7 +616,7 @@
|
|||
<label>
|
||||
<span class="component-title">Git executable path</span>
|
||||
<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>
|
||||
</span>
|
||||
</label>
|
||||
|
@ -615,7 +628,7 @@
|
|||
<span class="component-desc">
|
||||
<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)
|
||||
<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
|
||||
</select>
|
||||
<span>Disabled (default). High is lower and Low is higher CPU use</span>
|
||||
|
@ -627,7 +640,7 @@
|
|||
<label>
|
||||
<span class="component-title">Anonymous redirect</span>
|
||||
<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>
|
||||
</span>
|
||||
</label>
|
||||
|
@ -637,7 +650,7 @@
|
|||
<label for="encryption_version">
|
||||
<span class="component-title">Encrypt passwords</span>
|
||||
<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.
|
||||
<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>
|
||||
|
@ -648,7 +661,7 @@
|
|||
<label>
|
||||
<span class="component-title">Proxy host</span>
|
||||
<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>
|
||||
<div class="clear-left"><p>proxy address for connecting to providers (use 'PAC:Url' for PAC support)</p></div>
|
||||
</span>
|
||||
|
@ -659,7 +672,7 @@
|
|||
<label for="proxy_indexers">
|
||||
<span class="component-title">Use proxy for indexers</span>
|
||||
<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>
|
||||
</span>
|
||||
</label>
|
||||
|
@ -677,7 +690,7 @@
|
|||
#set $level_title = $level.title().upper()
|
||||
#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="$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
|
||||
</select>
|
||||
<span>(default: Db)</span>
|
||||
|
@ -691,7 +704,7 @@
|
|||
</div><!-- /component-group3 //-->
|
||||
|
||||
<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">
|
||||
|
||||
</div><!-- /config-components -->
|
||||
|
@ -709,4 +722,4 @@
|
|||
//-->
|
||||
</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')
|
||||
|
|
|
@ -104,17 +104,21 @@
|
|||
$x.providerType == $GenericProvider.TORRENT and $sickbeard.USE_TORRENTS]
|
||||
#set $cur_name = $cur_provider.get_id()
|
||||
#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 $tip = ($cur_provider.name + ('', ' (enable for link)')[not $cur_url and not cur_provider.is_enabled()],
|
||||
'Site Down')[$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 '' %>/>
|
||||
<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>
|
||||
#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>
|
||||
#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#
|
||||
<span class="ui-icon ui-icon-arrowthick-2-n-s pull-right" style="margin-top:3px"></span>
|
||||
</li>
|
||||
|
|
|
@ -1,75 +1,73 @@
|
|||
#import sickbeard
|
||||
#import datetime
|
||||
#import re
|
||||
#from sickbeard import subtitles, sbdatetime, network_timezones
|
||||
#import sickbeard.helpers
|
||||
#from sickbeard.common import *
|
||||
#from sickbeard.helpers import anon_url
|
||||
#from lib import subliminal
|
||||
#from sickbeard import indexerApi, indexermapper, network_timezones
|
||||
#from sickbeard.common import Overview, qualityPresets, qualityPresetStrings, \
|
||||
Quality, statusStrings, WANTED, SKIPPED, ARCHIVED, IGNORED, FAILED, DOWNLOADED
|
||||
#from sickbeard.helpers import anon_url, get_size, human, maybe_plural
|
||||
#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 $topmenu = 'home'
|
||||
#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
|
||||
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_top.tmpl')
|
||||
|
||||
<script type="text/javascript" src="$sbRoot/js/lib/jquery.bookmarkscroll.js?v=$sbPID"></script>
|
||||
|
||||
#include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_top.tmpl')
|
||||
<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/plotTooltip.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>
|
||||
#end if
|
||||
<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/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" charset="utf-8">
|
||||
<!--
|
||||
\$(document).ready(function(){
|
||||
#set $fuzzydate = 'airdate'
|
||||
#if $sickbeard.FUZZY_DATING
|
||||
fuzzyMoment({
|
||||
containerClass: '.${fuzzydate}',
|
||||
dateHasTime: !1,
|
||||
dateFormat: '${sickbeard.DATE_PRESET}',
|
||||
timeFormat: '${sickbeard.TIME_PRESET}',
|
||||
trimZero: #echo ('!1', '!0')[$sickbeard.TRIM_ZERO]#
|
||||
});
|
||||
|
||||
<style>
|
||||
.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}
|
||||
.images i{margin-right:6px;margin-top:5px}.hide{display:none}
|
||||
.tvshowImg {border:1px solid transparent;min-width:226px;min-hieght:332px}
|
||||
</style>
|
||||
<div class="bfr"><img src="$sbRoot/images/loading16${theme_suffix}.gif" /></div>
|
||||
|
||||
<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
|
||||
#raw
|
||||
$('.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>
|
||||
|
||||
<div class="displayshow-wrapper reg all">
|
||||
|
||||
<div class="background-container">
|
||||
<div style="" class="background"></div>
|
||||
</div>
|
||||
|
||||
<div class="pull-left form-inline">
|
||||
<div class="displayshow-wrapper">
|
||||
<div id="change-show" class="pull-left form-inline">
|
||||
Change show:
|
||||
#set $displayshowlist = []
|
||||
#set $cur_sel = 0
|
||||
|
@ -80,18 +78,19 @@
|
|||
#set void = $displayshowlist.append('\t\t\t<optgroup label="%s">' % $curShowType)
|
||||
#end if
|
||||
#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
|
||||
#if 1 < len($sortedShowLists)
|
||||
#set void = $displayshowlist.append('\t\t\t</optgroup>')
|
||||
#end if
|
||||
#end if
|
||||
#end for
|
||||
##
|
||||
<div class="navShow"><img id="prevShow" src="$sbRoot/images/prev.png" alt="<<" title="$prev_title" class="addQTip" /></div>
|
||||
<div id="prevShow" class="navShow addQTip" title="$prev_title"> </div>
|
||||
<select id="pickShow" class="form-control form-control-inline input-sm">
|
||||
#echo '\n'.join($displayshowlist)#
|
||||
</select>
|
||||
<div class="navShow"><img id="nextShow" src="$sbRoot/images/next.png" alt=">>" title="$next_title" class="addQTip" /></div>
|
||||
<div id="nextShow" class="navShow addQTip" title="$next_title"> </div>
|
||||
</div>
|
||||
|
||||
<div class="clearfix" style="margin-bottom:15px"></div>
|
||||
|
@ -104,52 +103,46 @@
|
|||
#end if
|
||||
<div class="display-show-container">
|
||||
<div id="posterCol" class="hidden-xs">
|
||||
<a href="$sbRoot/showPoster/?show=$show.indexerid&which=poster" rel="dialog" title="View poster for $show.name">
|
||||
<img src="$sbRoot/showPoster/?show=$show.indexerid&which=poster_thumb" class="tvshowImg" alt="" />
|
||||
<a href="$sbRoot/showPoster/?show=$show.indexerid&which=poster" rel="dialog">
|
||||
<img src="$sbRoot/showPoster/?show=$show.indexerid&which=poster_thumb" title="View poster for $show.name" class="tvshowImg addQTip" alt="">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div id="showCol" class="display-details">
|
||||
<div id="showCol">
|
||||
#if int($show.paused)
|
||||
<div class="paused paused-highlight">
|
||||
<i class="sgicon-pause paused-outline"></i>
|
||||
</div>
|
||||
#end if
|
||||
<div id="details-wrapper">
|
||||
<div id="details-right">
|
||||
#if 0 < len($seasonResults)
|
||||
##There is a special/season_0?##
|
||||
#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 class="details-wrapper">
|
||||
<div class="details-right top">
|
||||
#if 0 < len($seasons)
|
||||
#set $show_ended = '' != $show.status and $show.status in ['ended', 'Ended', 'Canceled']
|
||||
<div>
|
||||
#if $season_special
|
||||
#if $getVar('has_special', 0 == $seasons[-1][0])
|
||||
<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
|
||||
</div>
|
||||
#set $many_seasons = 12 < len($seasonResults)
|
||||
#set $many_seasons = 12 < len($seasons)
|
||||
<div class="details-seasons">
|
||||
<span class="details-title#echo ('', ' combo-seasons')[$many_seasons]#">Season</span>
|
||||
<span class="details-info">
|
||||
#set $season_list = [s[0] for s in $seasons]
|
||||
#if $many_seasons
|
||||
<select id="seasonJump" class="form-control form-control-inline input-sm">
|
||||
<option value="jump">Jump to season</option>
|
||||
#for $seasonNum in $seasonResults
|
||||
#if 0 == int($seasonNum['season'])
|
||||
#continue
|
||||
#for $number in $season_list
|
||||
#if 0 != $number
|
||||
<option value="#season-$number">Season $number</option>
|
||||
#end if
|
||||
<option value="#season-$seasonNum['season']">Season $seasonNum['season']</option>
|
||||
#end for
|
||||
</select>
|
||||
#else:
|
||||
#for $seasonNum in $seasonResults
|
||||
#if 0 == int($seasonNum['season'])
|
||||
#continue
|
||||
#else
|
||||
#for $number in $season_list
|
||||
#if 0 != $number
|
||||
<a href="#season-$number">$number</a>
|
||||
#end if
|
||||
<a href="#season-$seasonNum['season']">$seasonNum['season']</a>
|
||||
#end for
|
||||
#end if
|
||||
</span>
|
||||
|
@ -159,12 +152,12 @@
|
|||
|
||||
<div id="details-top">
|
||||
<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
|
||||
#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('|')
|
||||
#set $genres_done = True
|
||||
<span class="label"><a href="<%= anon_url('http://www.imdb.com/search/title?at=0&genres=', imdbgenre.lower().replace('-','_'),'&sort=moviemeter,asc&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('-','_'),'&sort=moviemeter,asc&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 if
|
||||
#if not $genres_done and $show.genre
|
||||
|
@ -180,45 +173,47 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div id="details-wrapper">
|
||||
<div id="details-right">
|
||||
<div class="details-wrapper">
|
||||
<div class="details-right">
|
||||
<div>
|
||||
<span class="details-title">Links</span>
|
||||
<span class="details-info">
|
||||
#set $tvdb_id = None
|
||||
#for $src_id, $src_name in $sickbeard.indexerApi().all_indexers.iteritems()
|
||||
#if sickbeard.indexerApi($src_id).config.get('defunct') and $src_id != $show.indexer
|
||||
#for $src_id, $src_name in $indexerApi().all_indexers.iteritems()
|
||||
#if $indexerApi($src_id).config.get('defunct') and $src_id != $show.indexer
|
||||
#continue
|
||||
#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
|
||||
#set $tvdb_id = $show.ids[$src_id]['id']
|
||||
#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
|
||||
#end if
|
||||
#if not sickbeard.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">
|
||||
#if not $indexerApi($src_id).config.get('defunct')
|
||||
<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#
|
||||
<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#
|
||||
<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>
|
||||
#end if
|
||||
#end for
|
||||
##if $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>
|
||||
##end if
|
||||
#if $has_art and $tvdb_id
|
||||
<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">
|
||||
<img alt="Fanart.tv" height="16" width="16" src="$sbRoot/images/fanart.png" />
|
||||
</a>
|
||||
#end if
|
||||
#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
|
||||
</span>
|
||||
</div>
|
||||
|
||||
#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
|
||||
#set $startyear = $show.imdb_info['year']
|
||||
#set $startyear = $show.imdb_info['year'] or None
|
||||
#end if
|
||||
#set $flags = 'country_codes' in $show.imdb_info and '' != $show.imdb_info['country_codes']
|
||||
#if 'runtimes' in $show.imdb_info
|
||||
|
@ -231,7 +226,7 @@
|
|||
#if None is $runtime and $show.runtime
|
||||
#set $runtime = $show.runtime
|
||||
#end if
|
||||
#if None is not $startyear or $flags
|
||||
#if $startyear or $flags
|
||||
<div>
|
||||
<span class="details-title">Premiered</span>
|
||||
<span class="details-info">
|
||||
|
@ -249,7 +244,7 @@
|
|||
#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)])
|
||||
<div>
|
||||
<span class="details-title">Airs</span>
|
||||
<span class="details-title">Air#echo ('s', 'ed')[$show_ended]#</span>
|
||||
<span class="details-info">$showairs</span>
|
||||
</div>
|
||||
#end if
|
||||
|
@ -266,18 +261,18 @@
|
|||
<span class="details-info">$runtime minutes</span>
|
||||
</div>
|
||||
#end if
|
||||
#if '' != $show.status
|
||||
#if $show.status
|
||||
<div>
|
||||
<span class="details-title">Status</span>
|
||||
<span class="details-info">$show.status</span>
|
||||
</div>
|
||||
#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>
|
||||
<span class="details-title">IMDb rating</span>
|
||||
<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']))
|
||||
<span class="imdbstars" qtip-content="$rating_tip">$show.imdb_info['rating']</span>
|
||||
#else
|
||||
|
@ -295,7 +290,7 @@
|
|||
<span class="quality $qualityPresetStrings[$show.quality]">$qualityPresetStrings[$show.quality]</span>
|
||||
</span>
|
||||
</div>
|
||||
#else:
|
||||
#else
|
||||
#if $anyQualities
|
||||
<div>
|
||||
<span class="details-title">Initial</span>
|
||||
|
@ -316,21 +311,37 @@
|
|||
</div>
|
||||
|
||||
<div id="details-left">
|
||||
<div class="details-plot#echo ('', ' no-plot')['' == $show.overview]#">
|
||||
#echo ('No plot overview available', $show.overview)['' != $show.overview]#
|
||||
#set $has_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 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="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>
|
||||
#set $filecount = sum([$c for $k, $c in $epCounts['videos'].items()])
|
||||
<span class="label addQTip" title="Videos">$filecount file$sickbeard.helpers.maybe_plural($filecount)</span>
|
||||
<span class="label addQTip" title="Size">$human($get_size($showLoc[0]))</span>
|
||||
#set $filecount = sum([$c for $k, $c in $ep_counts['videos'].items()])
|
||||
<span class="label addQTip" title="Videos">#echo ('No', $filecount)[0 < $filecount]# file$maybe_plural($filecount)</span>
|
||||
#if $show.paused
|
||||
<span class="label label-paused">Paused</span>
|
||||
#end if
|
||||
#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
|
||||
#if $show.exceptions
|
||||
<span class="label addQTip" title="$exceptions_string.replace(', ', '<br />')">Scene names</span>
|
||||
|
@ -341,7 +352,7 @@
|
|||
#if $show.rls_require_words
|
||||
<span class="label addQTip" title="#echo $show.rls_require_words.replace(',', '<br />')#">Required words</span>
|
||||
#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>
|
||||
#end if
|
||||
#if int($show.air_by_date)
|
||||
|
@ -353,7 +364,7 @@
|
|||
#if int($show.scene)
|
||||
<span class="label">Scene numbering</span>
|
||||
#end if
|
||||
#if $sickbeard.USE_SUBTITLES and int($show.subtitles)
|
||||
#if $sg_var('USE_SUBTITLES') and int($show.subtitles)
|
||||
<span class="label">Subtitles</span>
|
||||
#end if
|
||||
#if int($show.is_sports)
|
||||
|
@ -363,10 +374,10 @@
|
|||
<span class="label">Anime</span>
|
||||
#end if
|
||||
#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
|
||||
#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
|
||||
</div>
|
||||
</div>
|
||||
|
@ -376,7 +387,7 @@
|
|||
|
||||
<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>
|
||||
<select id="statusSelect" class="form-control form-control-inline input-sm">
|
||||
#for $curStatus in [$WANTED, $SKIPPED, $ARCHIVED, $IGNORED, $FAILED] + sorted($Quality.DOWNLOADED)
|
||||
|
@ -392,12 +403,12 @@
|
|||
</div>
|
||||
|
||||
<div class="pull-right clearfix" id="checkboxControls">
|
||||
<div style="padding-bottom:5px">
|
||||
<label for="wanted"><span class="wanted"><input type="checkbox" id="wanted" checked="checked"> Wanted: <b>$epCounts[$Overview.WANTED]</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="good"><span class="good"><input type="checkbox" id="good" checked="checked"> Downloaded: <b>$epCounts[$Overview.GOOD]</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="snatched"><span class="snatched"><input type="checkbox" id="snatched" checked="checked"> Snatched: <b>$epCounts[$Overview.SNATCHED]</b></span></label>
|
||||
<div style="padding-bottom:5px" class="addQTip" title="Filter Episodes">
|
||||
<label for="good"><span class="good"><input type="checkbox" id="good" checked="checked"> Downloaded: <b>$ep_counts[$Overview.GOOD]</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="wanted"><span class="wanted"><input type="checkbox" id="wanted" checked="checked"> Wanted: <b>$ep_counts[$Overview.WANTED]</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="skipped"><span class="skipped"><input type="checkbox" id="skipped" checked="checked"> Skipped: <b>$ep_counts[$Overview.SKIPPED]</b></span></label>
|
||||
</div>
|
||||
|
||||
<div class="pull-right" >
|
||||
|
@ -407,207 +418,94 @@
|
|||
</div>
|
||||
|
||||
<div class="clearfix"></div>
|
||||
#set $curSeason = -1
|
||||
#set $odd = 0
|
||||
#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
|
||||
##
|
||||
#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>
|
||||
#if not len($seasons)
|
||||
<div id="no-episode-data">
|
||||
<h3>No episode details at TV info source
|
||||
<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>
|
||||
</h3>
|
||||
</div>
|
||||
#else:
|
||||
#set $network_timezone = $network_timezones.get_network_timezone($show.network)
|
||||
#set $network_time = $network_timezones.parse_time($show.airs)
|
||||
#for $epResult in $sqlResults
|
||||
#set $epStr = '%sx%s' % ($epResult['season'], $epResult['episode'])
|
||||
#if not $epStr in $epCats or (0 == int($epResult['season']) and not $sickbeard.DISPLAY_SHOW_SPECIALS)
|
||||
#continue
|
||||
#else
|
||||
#set $working_season = -1
|
||||
#set $odd = 0
|
||||
#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
|
||||
##
|
||||
#if $curSeason != int($epResult['season'])
|
||||
#if 0 <= $curSeason
|
||||
|
||||
#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
|
||||
#end if
|
||||
#end if
|
||||
|
||||
#if $working_season != $season
|
||||
#if 0 <= $working_season
|
||||
</tbody>
|
||||
</table>
|
||||
#end if
|
||||
|
||||
<table class="sickbeardTable" cellspacing="0" border="0" cellpadding="0">
|
||||
<tr id="season-$epResult['season']">
|
||||
<th class="row-seasonheader" colspan="13">
|
||||
|
||||
<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>
|
||||
#set $videos = 'none' if $epResult['season'] not in $epCounts['videos'] else $epCounts['videos'][$epResult['season']]
|
||||
#set $archived = False if $epResult['season'] not in $epCounts['archived'] else $epCounts['archived'][$epResult['season']]
|
||||
<h3><a name="season-$epResult['season']"></a>#if 0 == int($epResult['season']) then 'Specials' else 'Season ' + str($epResult['season'])
|
||||
<span class="season-status"><b>[</b> <span class="footerhighlight">$videos</span> / <span class="footerhighlight">$epCounts['totals'][$epResult['season']]</span><span class="archived-count">#echo ('', ' with <span class="footerhighlight">%s</span> archived' % $archived)[0 < $archived]#</span> <b>]</b></span>
|
||||
</h3>
|
||||
</th>
|
||||
</tr>
|
||||
|
||||
<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-$epResult['season']-cols" class="seasoncols">
|
||||
<th class="col-checkbox"><input type="checkbox" class="seasonCheck" id="$epResult['season']"></th>
|
||||
<th class="col-metadata">NFO</th>
|
||||
<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-airdate">Airdate</th>
|
||||
#if $sickbeard.USE_SUBTITLES and $show.subtitles
|
||||
<th class="col-subtitles">Subtitles</th>
|
||||
#end if
|
||||
<th class="col-status">Status</th>
|
||||
<th class="col-search">Search</th>
|
||||
</tr>
|
||||
#set $curSeason = int($epResult['season'])
|
||||
#end if
|
||||
|
||||
#set $epLoc = $epResult['location']
|
||||
#set never_aired = 0 < $curSeason and 1 == int($epResult['airdate'])
|
||||
|
||||
<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 if
|
||||
</td>
|
||||
#end if
|
||||
#set $working_season = $season
|
||||
|
||||
#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
|
||||
#set $human_season = ('Season %s' % $season, 'Specials')[0 == $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">
|
||||
#if None is $has_art#<span class="red-text pull-right">Restart SickGear to reveal new options here</span>
|
||||
#elif not (1 == $lowest_season and 1 == $latest_season and $latest_season >= $highest_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>
|
||||
<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>
|
||||
<span class="images pull-right hide"><i class="spinner"></i></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"> D: <strong>$videos</strong> </span>#if snatched#<span class="snatched status-badge"> S: <strong>$snatched</strong> </span>#end if##if $wanted#<span class="wanted status-badge"> W: <strong>$wanted</strong> </span>#end if##if $qual#<span class="qual status-badge"> LQ: <strong>$qual</strong> </span>#end if# of <span class="footerhighlight">$ep_counts['totals'][$season]</span><span class="archived-count">#echo ('', ' with <span class="footerhighlight">%s</span> archived' % $archived)[0 < $archived]#</span></span>
|
||||
#end if
|
||||
</h3>
|
||||
</th>
|
||||
</tr>
|
||||
#set $attr_title_ep = ('', ' (Anime #)')[$show.is_anime]
|
||||
<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>
|
||||
<th class="col-metadata tablesorter-no-sort">Meta</th>
|
||||
<th class="col-ep tablesorter-ep-num"><span title="Ep #$attr_title_ep">#</span></th>#if $scene or $scene_anime
|
||||
<th class="col-ep tablesorter-ep-scene" style="padding-right:18px">Scene#if $scene_anime# absolute#end if#</th>#end if#
|
||||
<th class="col-name">Name</th>
|
||||
<th class="col-airdate tablesorter-airdate">Air Date</th>#if $sg_var('USE_SUBTITLES') and $show.subtitles
|
||||
<th class="col-subtitles tablesorter-no-sort">Subtitles</th>#end if
|
||||
<th class="col-status">Status</th>
|
||||
<th class="col-search tablesorter-no-sort">Search</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<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&season=$epResult['season']&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&season=$epResult['season']&episode=$epResult['episode']"><img src="$sbRoot/images/search16.png" width="16" height="16" alt="search" title="Manual search" /></a>
|
||||
#end if
|
||||
#end if
|
||||
<tbody class="collapse">
|
||||
#end if
|
||||
#if None is $ep
|
||||
</tbody>
|
||||
#continue
|
||||
#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&season=$epResult['season']&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
|
||||
#set global $episode = $ep
|
||||
#include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_displayShow.tmpl')
|
||||
#end for
|
||||
#end for
|
||||
</tbody>
|
||||
</table>
|
||||
#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>
|
||||
#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')
|
||||
|
|
|
@ -1,29 +1,32 @@
|
|||
#import sickbeard
|
||||
#import lib.adba as adba
|
||||
#from sickbeard import common
|
||||
#from sickbeard import exceptions
|
||||
#from sickbeard import scene_exceptions
|
||||
#from sickbeard import (blackandwhitelist, common, exceptions, helpers, scene_exceptions)
|
||||
#from sickbeard.helpers import anon_url
|
||||
#from sickbeard.indexers.indexer_config import INDEXER_TVDB
|
||||
#import sickbeard.blackandwhitelist
|
||||
<% 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 = 'Edit ' + $show.name
|
||||
#set global $header = $show.name
|
||||
#set global $sbPath = '..'
|
||||
#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
|
||||
#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/editShow.js?v=$sbPID"></script>
|
||||
<script>
|
||||
var config = {showLang: '$show.lang', showIsAnime: #echo ['!1','!0'][$show.is_anime]#}
|
||||
</script>
|
||||
<script type="text/javascript" src="$sbRoot/js/livepanel.js?v=$sbPID"></script>
|
||||
#if $varExists('header')
|
||||
<h1 class="header"><span class="grey-text">Edit</span> $header</h1>
|
||||
<h1 class="header"><span class="grey-text">Edit </span>$header</h1>
|
||||
#else
|
||||
<h1 class="title">$title</h1>
|
||||
#end if
|
||||
|
@ -31,6 +34,21 @@
|
|||
##
|
||||
#set $html_checked = ' checked="checked"'
|
||||
#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-content" class="linefix container">
|
||||
<form action="editShow" method="post" id="editShow" style="width:894px">
|
||||
|
@ -48,20 +66,20 @@
|
|||
|
||||
<div class="field-pair">
|
||||
<label for="paused">
|
||||
<span class="component-title">Paused</span>
|
||||
<span class="component-title">Pause searching releases</span>
|
||||
<span class="component-desc">
|
||||
<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>
|
||||
</label>
|
||||
</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">
|
||||
<span class="component-title">Group show under</span>
|
||||
<span class="component-desc">
|
||||
<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>
|
||||
#end for
|
||||
</select>
|
||||
|
@ -72,9 +90,9 @@
|
|||
|
||||
<div class="field-pair">
|
||||
<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">
|
||||
<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]#">
|
||||
<option value="-1">Series</option>
|
||||
#if $show.anime:
|
||||
|
@ -84,8 +102,8 @@
|
|||
#end if
|
||||
</select>
|
||||
<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 class="clear-left note">post-processing or searching may require an alternative if a "Show not found" error is reported</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">searching and post-processing require the alternatives if "Show not found" errors are in the logs</p>
|
||||
</span>
|
||||
<span id="SceneException" class="component-desc" style="display:none">
|
||||
<h4 class="grey-text">Alternative a.k.a scene exceptions list (multi-selectable)</h4>
|
||||
|
@ -96,7 +114,7 @@
|
|||
#end for
|
||||
#end for
|
||||
</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>
|
||||
<input id="removeSceneName" value="Remove" class="btn pull-left" type="button" style="margin-top: 10px;"/>
|
||||
</div>
|
||||
|
@ -130,7 +148,7 @@
|
|||
#set $qualities = $common.Quality.splitQuality(int($show.quality))
|
||||
#set global $anyQualities = $qualities[0]
|
||||
#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
|
||||
<div class="field-pair show-if-quality-custom" style="display:none">
|
||||
|
@ -213,7 +231,7 @@
|
|||
|
||||
#if $show.is_anime
|
||||
#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>
|
||||
#end if
|
||||
</div><!-- /component-group2 //-->
|
||||
|
@ -233,7 +251,7 @@
|
|||
<label for="flatten_folders">
|
||||
<span class="component-title">Flat folder hierarchy</span>
|
||||
<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>
|
||||
</span>
|
||||
</label>
|
||||
|
@ -243,8 +261,27 @@
|
|||
<label for="subtitles">
|
||||
<span class="component-title">Subtitles</span>
|
||||
<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]#>
|
||||
<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>
|
||||
<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 $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: </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: </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>
|
||||
</label>
|
||||
</div>
|
||||
|
@ -327,7 +364,7 @@
|
|||
<p>for unlocked IDs</p>
|
||||
</span>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -344,4 +381,4 @@
|
|||
</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')
|
||||
|
|
|
@ -6,15 +6,17 @@
|
|||
#from sickbeard import history
|
||||
#from sickbeard import providers
|
||||
#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 $header = 'History'
|
||||
#set global $sbPath = '..'
|
||||
#set global $topmenu = 'history'
|
||||
#set $layout = $sickbeard.HISTORY_LAYOUT
|
||||
#set $layout = $sg_str('HISTORY_LAYOUT', 'detailed')
|
||||
##
|
||||
#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">
|
||||
<!--
|
||||
|
@ -61,13 +63,13 @@
|
|||
});
|
||||
|
||||
#set $fuzzydate = 'airdate'
|
||||
#if $sickbeard.FUZZY_DATING
|
||||
#if $sg_var('FUZZY_DATING')
|
||||
fuzzyMoment({
|
||||
containerClass: '.${fuzzydate}',
|
||||
dateHasTime: !0,
|
||||
dateFormat: '${sickbeard.DATE_PRESET}',
|
||||
timeFormat: '${sickbeard.TIME_PRESET_W_SECONDS}',
|
||||
trimZero: #echo ('!1', '!0')[$sickbeard.TRIM_ZERO]#,
|
||||
dateFormat: '$sg_str('DATE_PRESET', '%x')',
|
||||
timeFormat: '$sg_str('TIME_PRESET_W_SECONDS', '%I:%M:%S %p')',
|
||||
trimZero: #echo ('!1', '!0')[$sg_var('TRIM_ZERO')]#,
|
||||
dtGlue: ', '
|
||||
});
|
||||
#end if
|
||||
|
@ -93,8 +95,8 @@
|
|||
|
||||
<span style="margin-left:5px">Layout:
|
||||
<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=detailed"#echo ('', $html_selected)['detailed' == $sickbeard.HISTORY_LAYOUT]#>Detailed</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' == $sg_str('HISTORY_LAYOUT', 'detailed')]#>Detailed</option>
|
||||
</select>
|
||||
</span>
|
||||
</div>
|
||||
|
@ -121,10 +123,10 @@
|
|||
<tbody>
|
||||
#for $hItem in $historyResults
|
||||
#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>' % (
|
||||
$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']))
|
||||
<tr>
|
||||
#set $curdatetime = $datetime.datetime.strptime(str($hItem['date']), $history.dateFormat)
|
||||
|
@ -156,7 +158,7 @@
|
|||
#end if
|
||||
#end if
|
||||
</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>
|
||||
#end for
|
||||
|
||||
|
@ -164,10 +166,10 @@
|
|||
<thead>
|
||||
<tr>
|
||||
<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>Downloaded</th>
|
||||
#if sickbeard.USE_SUBTITLES
|
||||
#if $sg_var('USE_SUBTITLES')
|
||||
<th>Subtitled</th>
|
||||
#end if
|
||||
<th width="14%">Quality</th>
|
||||
|
@ -183,10 +185,10 @@
|
|||
<tbody>
|
||||
#for $hItem in $compactResults
|
||||
#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>' % (
|
||||
$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']))
|
||||
#set $prov_list = []
|
||||
#set $down_list = []
|
||||
|
@ -245,7 +247,7 @@
|
|||
<td>
|
||||
#echo ' '.join($down_list)#
|
||||
</td>
|
||||
#if sickbeard.USE_SUBTITLES
|
||||
#if $sg_var('USE_SUBTITLES')
|
||||
<td>
|
||||
#for $action in reversed($hItem['actions'])
|
||||
#set $curStatus, $curQuality = $Quality.splitCompositeStatus(int($action['action']))
|
||||
|
@ -258,7 +260,7 @@
|
|||
#end for
|
||||
</td>
|
||||
#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>
|
||||
#end for
|
||||
|
||||
|
@ -266,4 +268,4 @@
|
|||
</tbody>
|
||||
</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')
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
#import datetime
|
||||
#from sickbeard.common import *
|
||||
#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 $header = 'Show List'
|
||||
|
@ -11,18 +13,18 @@
|
|||
#set fuzzydate = 'airdate'
|
||||
##
|
||||
#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>
|
||||
var config = {
|
||||
isPoster: #echo ['!1','!0']['poster' == $sickbeard.HOME_LAYOUT]#,
|
||||
sortArticle: #echo ['!1','!0'][$sickbeard.SORT_ARTICLE]#,
|
||||
homeSearchFocus: #echo ['!1','!0'][$sickbeard.HOME_SEARCH_FOCUS]#,
|
||||
fuzzyDating: #echo ['!1','!0'][$sickbeard.FUZZY_DATING]#,
|
||||
timeZero: #echo ['!1','!0'][$sickbeard.TRIM_ZERO]#,
|
||||
datePreset: "$sickbeard.DATE_PRESET",
|
||||
timePreset: "$sickbeard.TIME_PRESET",
|
||||
posterSortby: "$sickbeard.POSTER_SORTBY",
|
||||
posterSortdir: #echo ['!1','!0'][$sickbeard.POSTER_SORTDIR]#,
|
||||
isPoster: #echo ['!1','!0']['poster' == $sg_var('HOME_LAYOUT')]#,
|
||||
sortArticle: #echo ['!1','!0'][$sg_var('SORT_ARTICLE')]#,
|
||||
homeSearchFocus: #echo ['!1','!0'][$sg_var('HOME_SEARCH_FOCUS', True)]#,
|
||||
fuzzyDating: #echo ['!1','!0'][$sg_var('FUZZY_DATING')]#,
|
||||
timeZero: #echo ['!1','!0'][$sg_var('TRIM_ZERO')]#,
|
||||
datePreset: "$sg_str('DATE_PRESET', '%x')",
|
||||
timePreset: "$sg_str('TIME_PRESET', '%I:%M %p')",
|
||||
posterSortby: "$sg_var('POSTER_SORTBY')",
|
||||
posterSortdir: #echo ['!1','!0'][$sg_var('POSTER_SORTDIR', True)]#,
|
||||
fuzzydate: ".$fuzzydate",
|
||||
};
|
||||
</script>
|
||||
|
@ -33,33 +35,33 @@
|
|||
#set $tab = 1
|
||||
#set $selected = ' selected="selected"'
|
||||
#if 'poster' == $layout
|
||||
<div>
|
||||
<div id="top-row">
|
||||
<span>Sort By:
|
||||
<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="date" data-sort="$sbRoot/setPosterSortBy/?sort=date"#echo $selected if 'date' == sickbeard.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="progress" data-sort="$sbRoot/setPosterSortBy/?sort=progress"#echo $selected if 'progress' == sickbeard.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="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' == $sg_str('POSTER_SORTBY') else ''#>Next Episode</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' == $sg_str('POSTER_SORTBY') else ''#>Progress</option>
|
||||
<option value="quality" data-sort="$sbRoot/setPosterSortBy/?sort=quality"#echo $selected if 'quality' == $sg_str('POSTER_SORTBY') else ''#>Quality</option>
|
||||
</select>
|
||||
</span>
|
||||
|
||||
<span style="margin-left:5px">Sort Order:
|
||||
<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="false" data-sort="$sbRoot/setPosterSortDir/?direction=0"#echo $selected if 0 == sickbeard.POSTER_SORTDIR else ''#>Desc</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 == $sg_var('POSTER_SORTDIR') else ''#>Desc</option>
|
||||
</select>
|
||||
</span>
|
||||
|
||||
<span style="margin-left:5px">Layout:
|
||||
<span style="margin-left:5px" class="no-marginr">Layout:
|
||||
#else
|
||||
<span class="pull-right">Layout:
|
||||
<span id="top-row" class="pull-right no-marginr">Layout:
|
||||
#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#">
|
||||
<option value="$sbRoot/setHomeLayout/?layout=poster"#echo $selected if 'poster' == sickbeard.HOME_LAYOUT 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=banner"#echo $selected if 'banner' == sickbeard.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=poster"#echo $selected if 'poster' == $sg_str('HOME_LAYOUT', 'poster') else ''#>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' == $sg_str('HOME_LAYOUT') else ''#>Banner</option>
|
||||
<option value="$sbRoot/setHomeLayout/?layout=simple"#echo $selected if 'simple' == $sg_str('HOME_LAYOUT') else ''#>Simple</option>
|
||||
</select>
|
||||
</span>
|
||||
|
||||
|
@ -89,7 +91,7 @@
|
|||
##
|
||||
#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
|
||||
#end if
|
||||
##
|
||||
|
@ -116,7 +118,7 @@
|
|||
#set $cur_total = 0
|
||||
#set $download_stat_tip = ''
|
||||
#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 re.search(r'(?i)(?:new|returning)\s*series', $curShow.status)
|
||||
#set $display_status = 'Continuing'
|
||||
|
@ -272,7 +274,7 @@
|
|||
|
||||
<tbody>
|
||||
#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
|
||||
#end if
|
||||
##
|
||||
|
@ -302,7 +304,7 @@
|
|||
#set $cur_downloaded = 0
|
||||
#set $cur_total = 0
|
||||
#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
|
||||
#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')
|
||||
|
|
|
@ -1,22 +1,24 @@
|
|||
#import sickbeard
|
||||
#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 $header = 'Existing Show'
|
||||
#set global $title = 'Import'
|
||||
#set global $header = $title
|
||||
#set global $sbPath = '../..'
|
||||
#set global $statpath = '../..'
|
||||
#set global $topmenu = 'home'
|
||||
##
|
||||
#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">
|
||||
<!--
|
||||
var config = { sortArticle: #echo ['!1','!0'][$sickbeard.SORT_ARTICLE]# }
|
||||
var config = { sortArticle: #echo ['!1','!0'][$sg_var('SORT_ARTICLE')]# }
|
||||
\$.sgSid = '$kwargs.get('sid', '')';
|
||||
\$.sgHashDir = '$kwargs.get('hash_dir', '')';
|
||||
\$(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>
|
||||
|
@ -31,8 +33,9 @@ var config = { sortArticle: #echo ['!1','!0'][$sickbeard.SORT_ARTICLE]# }
|
|||
<h1 class="title">$title</h1>
|
||||
#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">
|
||||
|
||||
<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>
|
||||
<div id="tabs-1" class="existingtabs">
|
||||
<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 id="tabs-2">
|
||||
<div class="stepDiv">
|
||||
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_addShowOptions.tmpl')
|
||||
<div class="stepDiv" style="padding-top:25px">
|
||||
#include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_addShowOptions.tmpl')
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -87,4 +90,4 @@ var config = { sortArticle: #echo ['!1','!0'][$sickbeard.SORT_ARTICLE]# }
|
|||
|
||||
</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')
|
||||
|
|
|
@ -18,36 +18,36 @@
|
|||
|
||||
<div id="addShowPortal">
|
||||
<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">
|
||||
<h3>Add new show</h3>
|
||||
<p>Search a TV database for a show.</p>
|
||||
<h3>Search</h3>
|
||||
<p>find show at TV info source</p>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<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">
|
||||
<h3>Add from Trakt</h3>
|
||||
<p>Browse trends, recommended and more.</p>
|
||||
<h3>Trakt cards</h3>
|
||||
<p>trends, tailored suggestions...</p>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<div style="clear:both;font-size:2px"> </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="buttontext">
|
||||
<h3>Add existing shows</h3>
|
||||
<p>Scan parent folders to import into SickGear.</p>
|
||||
<h3>Import</h3>
|
||||
<p>existing shows</p>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<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">
|
||||
<h3>Add from IMDb</h3>
|
||||
<p>Browse popular for a show to add.</p>
|
||||
<h3>IMDb cards</h3>
|
||||
<p>popular decades, watchlists...</p>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
|
@ -57,16 +57,16 @@
|
|||
<a class="btn btn-large" href="$sbRoot/home/addShows/anime_default/">
|
||||
<div class="button"><div class="img-anime square-32"></div></div>
|
||||
<div class="buttontext">
|
||||
<h3>Add anime show</h3>
|
||||
<p>Browse anime to add.</p>
|
||||
<h3>Anime cards</h3>
|
||||
<p>browse anime to add</p>
|
||||
</div>
|
||||
</a>
|
||||
#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="buttontext">
|
||||
<h3>Add anime show</h3>
|
||||
<p>To use, enable AniDB in <a href="$sbRoot/config/anime/">Config/Anime</a>.</p>
|
||||
<h3>Anime cards</h3>
|
||||
<p>to use, enable AniDB <a href="$sbRoot/config/anime/">here</a></p>
|
||||
</div>
|
||||
</div>
|
||||
#end if
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#from sickbeard.common import *
|
||||
#from sickbeard import sbdatetime
|
||||
#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 $header='Browse Shows'
|
||||
|
@ -13,7 +15,7 @@
|
|||
#set global $page_body_attr = 'browse-list'
|
||||
##
|
||||
#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>
|
||||
|
||||
|
@ -51,7 +53,7 @@
|
|||
premiered: '[data-premiered] parseInt',
|
||||
name: function( itemElem ) {
|
||||
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');
|
||||
#end if
|
||||
return name.toLowerCase();
|
||||
|
@ -128,21 +130,6 @@
|
|||
<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=".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"'
|
||||
#if 'Trakt' == $browse_type
|
||||
<optgroup label="Trakt">
|
||||
|
@ -162,11 +149,11 @@
|
|||
<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>
|
||||
</optgroup>
|
||||
#if any($sickbeard.TRAKT_ACCOUNTS)
|
||||
#if any($sg_var('TRAKT_ACCOUNTS', []))
|
||||
<optgroup label="Trakt recommended">
|
||||
#for $account in $sickbeard.TRAKT_ACCOUNTS
|
||||
#if $sickbeard.TRAKT_ACCOUNTS[$account].active and $sickbeard.TRAKT_ACCOUNTS[$account].name
|
||||
<option value="trakt_recommended?account=$account"#echo ('', selected)[('recommended-%s' % $account) == $mode]#>for $sickbeard.TRAKT_ACCOUNTS[$account].name</option>
|
||||
#for $account in $sg_var('TRAKT_ACCOUNTS')
|
||||
#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 $sg_var('TRAKT_ACCOUNTS').get($account).name</option>
|
||||
#end if
|
||||
#end for
|
||||
#else
|
||||
|
@ -186,8 +173,8 @@
|
|||
#end if
|
||||
#if not hasattr($sickbeard, 'IMDB_ACCOUNTS')#<optgroup label="Restart SickGear to reveal"><option>new options after restart</option></optgroup>#else#
|
||||
<optgroup label="IMDb Watchlists">
|
||||
#if any($sickbeard.IMDB_ACCOUNTS)
|
||||
#for $i, $v in $enumerate($sickbeard.IMDB_ACCOUNTS)
|
||||
#if any($sg_var('IMDB_ACCOUNTS', []))
|
||||
#for $i, $v in $enumerate($sg_var('IMDB_ACCOUNTS'))
|
||||
#if not $i % 2
|
||||
#set $id = $v
|
||||
#elif not $v.startswith('(Off) ')
|
||||
|
@ -256,11 +243,11 @@
|
|||
</div>
|
||||
|
||||
<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> </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> </span>')['' == $this_show['title']]#
|
||||
</div>
|
||||
|
||||
<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']:
|
||||
<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>">
|
||||
|
@ -269,7 +256,7 @@
|
|||
|
||||
<div class="browse-add-show-holder">
|
||||
#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
|
||||
<a href="$sbRoot/home/addShows/add${browse_type}Show?indexer_id=${this_show['show_id']}&showName=${urllib.quote($this_show['title'].encode("utf-8"))}" class="btn btn-xs">Add Show</a>
|
||||
#end if
|
||||
|
@ -308,4 +295,4 @@ window.setInterval('location.reload(true)', 600000); // Refresh every 10 minutes
|
|||
//-->
|
||||
</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')
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
#import sickbeard
|
||||
#from sickbeard.helpers import anon_url
|
||||
##
|
||||
#set global $header = 'New Show'
|
||||
#set global $title = 'New Show'
|
||||
#set global $header = 'Add from TV info source'
|
||||
#set global $title = $header
|
||||
#set global $sbPath = '../..'
|
||||
#set global $statpath = '../..'
|
||||
#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
|
||||
#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
|
||||
|
||||
|
@ -27,7 +29,7 @@
|
|||
<h1 class="title">$title</h1>
|
||||
#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">
|
||||
|
||||
|
@ -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>
|
||||
|
||||
<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" />
|
||||
|
||||
#if $use_provided_info
|
||||
|
@ -58,7 +60,7 @@
|
|||
</style>
|
||||
<input type="hidden" id="providedIndexer" value="$provided_indexer" />
|
||||
#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" />
|
||||
|
||||
<span style="float:right">
|
||||
<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" />
|
||||
</span>
|
||||
<br />
|
||||
<p style="margin:5px 0 15px">Enter show name, TVDB ID, IMDb Url, or IMDb ID. <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. </span><b>*</b>SickGear supports english, language is used for show/episode data</p>
|
||||
|
||||
<div id="searchResults" style="height: 100%"></div>
|
||||
#end if
|
||||
|
@ -94,7 +96,7 @@
|
|||
Pre-chosen Destination Folder: <b>$provided_show_dir</b> <br />
|
||||
<input type="hidden" id="fullShowPath" name="fullShowPath" value="$provided_show_dir" /><br />
|
||||
#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
|
||||
</div>
|
||||
<div style="clear:both"> </div>
|
||||
|
@ -103,7 +105,7 @@
|
|||
<fieldset class="sectionwrap step-three" style="visibility:hidden">
|
||||
<legend class="legendStep"><p>Set custom options</p></legend>
|
||||
<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 style="clear:both"> </div>
|
||||
</fieldset>
|
||||
|
@ -128,4 +130,4 @@
|
|||
|
||||
</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')
|
||||
|
|
|
@ -1,14 +1,25 @@
|
|||
#import sickbeard
|
||||
#from sickbeard.common import *
|
||||
#from sickbeard import subtitles
|
||||
<div class="stepDiv linefix">
|
||||
##
|
||||
#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 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 <input class="btn btn-inline" type="button" id="saveDefaultsButton" value="Save as defaults" disabled="disabled" /></span>
|
||||
</div>
|
||||
|
||||
<div class="field-pair">
|
||||
<label for="statusSelect">
|
||||
<span class="component-title">Initial episode status</span>
|
||||
<span class="component-desc">
|
||||
<select name="defaultStatus" id="statusSelect" class="form-control form-control-inline input-sm">
|
||||
#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
|
||||
</select>
|
||||
<span>set the initial status of missing episodes</span>
|
||||
|
@ -21,10 +32,10 @@
|
|||
</div>
|
||||
|
||||
<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 $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>
|
||||
|
||||
#try:
|
||||
|
@ -33,14 +44,14 @@
|
|||
<span class="component-title">From season 1 forward, set</span>
|
||||
<span class="component-desc">
|
||||
<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>
|
||||
</label>
|
||||
</span>
|
||||
<span class="component-title">From latest going back, set</span>
|
||||
<span class="component-desc">
|
||||
<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>
|
||||
</label>
|
||||
</span>
|
||||
|
@ -50,13 +61,13 @@
|
|||
#pass
|
||||
#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">
|
||||
<span class="component-title">Place show in group</span>
|
||||
<span class="component-desc">
|
||||
<select name="tag" id="tag" class="form-control form-control-inline input-sm">
|
||||
#for $tag in $sickbeard.SHOW_TAGS:
|
||||
<option value="$tag" #if $tag == $getattr(sickbeard, 'SHOW_TAG_DEFAULT', $getattr(sickbeard, 'DEFAULT_SHOW_TAG', None)) then 'selected="selected"' else ''#>$tag</option>
|
||||
#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 else ''#>$tag</option>
|
||||
#end for
|
||||
</select>
|
||||
<span>and display on the show list page under this section</span>
|
||||
|
@ -68,7 +79,7 @@
|
|||
<label for="flatten_folders">
|
||||
<span class="component-title">Flat folder structure</span>
|
||||
<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>
|
||||
</span>
|
||||
</label>
|
||||
|
@ -78,18 +89,18 @@
|
|||
<label for="scene">
|
||||
<span class="component-title">Scene numbering</span>
|
||||
<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>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
#if $sickbeard.USE_SUBTITLES:
|
||||
#if $sg_var('USE_SUBTITLES'):
|
||||
<div class="field-pair alt">
|
||||
<label for="subtitles">
|
||||
<span class="component-title">Subtitles</span>
|
||||
<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>
|
||||
</span>
|
||||
</label>
|
||||
|
@ -101,27 +112,18 @@
|
|||
<label for="anime">
|
||||
<span class="component-title">Show is anime</span>
|
||||
<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>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
#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>
|
||||
|
||||
#if $enable_anime_options
|
||||
#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
|
||||
<input type="hidden" name="anime" id="anime" value="0" />
|
||||
#end if
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#import re
|
||||
#from sickbeard import db, sbdatetime
|
||||
#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><!-- /contentWrapper -->
|
||||
|
@ -26,8 +28,8 @@
|
|||
##
|
||||
#set $sql_result = $my_db.select($sql_statement)
|
||||
##
|
||||
#set $shows_total = len($sickbeard.showList)
|
||||
#set $shows_active = len([show for show in $sickbeard.showList if 0 == show.paused and 'Ended' != show.status])
|
||||
#set $shows_total = len($sg_str('showList'))
|
||||
#set $shows_active = len([show for show in $sg_str('showList') if 0 == show.paused and 'Ended' != show.status])
|
||||
##
|
||||
#if $sql_result:
|
||||
#set $ep_snatched = $sql_result[0]['ep_snatched']
|
||||
|
|
125
gui/slick/interfaces/default/inc_displayShow.tmpl
Normal 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&season=$ep['season']&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&season=$ep['season']&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&season=$ep['season']&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
|
59
gui/slick/interfaces/default/inc_livepanel.tmpl
Normal 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, '§=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>
|
|
@ -5,7 +5,7 @@
|
|||
<div class="field-pair">
|
||||
<label for="qualityPreset" class="clearfix">
|
||||
#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">
|
||||
#set $selected = None
|
||||
<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>
|
||||
#end for
|
||||
</select>
|
||||
<span>preferred episode quality to download</span>
|
||||
<span>tip: select a quality then "Custom" for a default selection</span>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
|
@ -22,8 +22,9 @@
|
|||
<div id="customQualityWrapper">
|
||||
<div id="customQuality" class="show-if-quality-custom" style="display:none">
|
||||
<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>Upgrades continue until the highest selected of <em>Upgrade to</em> is matched.</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>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>
|
||||
|
||||
<span class="component-desc">
|
||||
|
@ -48,6 +49,7 @@
|
|||
#end for
|
||||
</select><br />
|
||||
<span>Ctrl + Click = toggle a quality</span>
|
||||
<br /><span>Ctrl + Click = toggle a quality</span>
|
||||
</div>
|
||||
|
||||
<div style="line-height:normal;padding-top:50px" id="quality-notes" class="tip-text">
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#import sickbeard
|
||||
#import urllib
|
||||
#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
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
@ -35,6 +37,7 @@
|
|||
<meta name="msapplication-TileColor" content="#2b5797">
|
||||
<meta name="msapplication-TileImage" content="$sbRoot/images/ico/mstile-144x144.png">
|
||||
<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/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/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/${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/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/script.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/fuzzyMoment.js?v=$sbPID"></script>
|
||||
#end if
|
||||
<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';
|
||||
\$.SickGear = {Root: '${sbRoot}', PID: '${sbPID}'};
|
||||
//-->
|
||||
|
@ -86,6 +89,10 @@
|
|||
#except
|
||||
#pass
|
||||
#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>
|
||||
<nav class="navbar navbar-default navbar-fixed-top" role="navigation">
|
||||
<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>
|
||||
<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/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 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>
|
||||
</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/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>
|
||||
#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>
|
||||
#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>
|
||||
#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>
|
||||
#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>
|
||||
#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>
|
||||
#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>
|
||||
#end if
|
||||
</ul>
|
||||
</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">
|
||||
<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">
|
||||
|
@ -171,12 +184,22 @@
|
|||
</li>
|
||||
|
||||
<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">
|
||||
<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>
|
||||
#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>
|
||||
#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>
|
||||
|
@ -224,9 +247,9 @@
|
|||
</p>
|
||||
</div>
|
||||
#end if
|
||||
#if $sickbeard.NEWEST_VERSION_STRING
|
||||
#if $sg_str('NEWEST_VERSION_STRING')
|
||||
<div class="alert alert-success upgrade-notification" role="alert">
|
||||
<span>$sickbeard.NEWEST_VERSION_STRING</span>
|
||||
<span>$sg_str('NEWEST_VERSION_STRING')</span>
|
||||
</div>
|
||||
#end if
|
||||
##
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#import sickbeard
|
||||
#from sickbeard import common
|
||||
#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 $header = 'Mass Edit'
|
||||
|
@ -8,7 +10,7 @@
|
|||
#set global $topmenu = 'manage'
|
||||
##
|
||||
#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:
|
||||
#set $initial_quality = int($quality_value)
|
||||
|
@ -88,7 +90,7 @@
|
|||
#set $isDisabled = $isSelected
|
||||
#if $archive_firstmatch_value##set $isDisabled = ''##else##set $isEnabled = ''##end if#
|
||||
<div class="optionWrapper clearfix">
|
||||
<span class="selectTitle">End upgrade on first match</span>
|
||||
<span class="selectTitle">Upgrade once</span>
|
||||
<div class="selectChoices">
|
||||
<select id="edit_archive_firstmatch" name="archive_firstmatch" class="form-control form-control-inline input-sm">
|
||||
<option value="keep">< keep ></option>
|
||||
|
@ -165,12 +167,12 @@
|
|||
</div><br />
|
||||
</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>
|
||||
<div class="selectChoices">
|
||||
<select id="edit_tag" name="tag" class="form-control form-control-inline input-sm">
|
||||
<option value="keep">< keep ></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>
|
||||
#end for
|
||||
</select>
|
||||
|
@ -194,4 +196,4 @@
|
|||
//-->
|
||||
</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')
|
||||
|
|
|
@ -2,97 +2,128 @@
|
|||
#from sickbeard import common
|
||||
#from sickbeard import exceptions
|
||||
##
|
||||
#set global $title = 'Test Rename ' + $show.name
|
||||
#set global $header = '<a href="' + $sbRoot + '/home/displayShow?show=%d">%s</a>' % ($show.indexerid, $show.name)
|
||||
#set global $title = 'Media Renamer ' + $show.name
|
||||
#set global $header = $show.name
|
||||
#set global $sbPath = '..'
|
||||
#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
|
||||
#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')
|
||||
<h1 class="header">$header</h1>
|
||||
<h1 class="header"><span class="grey-text">Media Renamer </span>$header</h1>
|
||||
#else
|
||||
<h1 class="title">$title</h1>
|
||||
#end if
|
||||
|
||||
<input type="hidden" id="showID" value="$show.indexerid" />
|
||||
|
||||
<script type="text/javascript" src="$sbRoot/js/testRename.js"></script>
|
||||
|
||||
<h3>Preview of the proposed name changes</h3>
|
||||
<blockquote>
|
||||
#if int($show.air_by_date) == 1 and $sickbeard.NAMING_CUSTOM_ABD:
|
||||
$sickbeard.NAMING_ABD_PATTERN
|
||||
#elif int($show.sports) == 1 and $sickbeard.NAMING_CUSTOM_SPORTS:
|
||||
$sickbeard.NAMING_SPORTS_PATTERN
|
||||
#else
|
||||
$sickbeard.NAMING_PATTERN
|
||||
<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
|
||||
</blockquote>
|
||||
</div>
|
||||
|
||||
##
|
||||
<div id="config">
|
||||
<div id="config-content" class="linefix container">
|
||||
<input type="hidden" id="showID" value="$show.indexerid">
|
||||
|
||||
<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> <a href="$sbRoot/config/postProcessing/#core-component-group2">edit pattern</a>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button class="btn seriesCheck">Select All Episodes</button>
|
||||
<button class="btn clearAll">Clear All</button>
|
||||
</div>
|
||||
#set $curSeason = -1
|
||||
#set $odd = False
|
||||
<div class="clearfix padbottom">
|
||||
<button class="btn seriesCheck">Select All Episodes</button>
|
||||
<button class="btn clearAll">Clear All</button>
|
||||
</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>
|
||||
|
||||
<table id="testRenameTable" class="sickbeardTable" border="0">
|
||||
#set $first_season = True
|
||||
<table id="testRenameTable" class="sickbeardTable" border="0">
|
||||
##
|
||||
#for $cur_ep_obj in $ep_obj_list
|
||||
#set $curLoc = $cur_ep_obj.location[len($cur_ep_obj.show.location)+1:]
|
||||
#set $curExt = $curLoc.split('.')[-1]
|
||||
#set $newLoc = $cur_ep_obj.proper_path() + '.' + $curExt
|
||||
|
||||
#if int($cur_ep_obj.season) != $curSeason:
|
||||
<thead>
|
||||
<tr class="seasonheader" id="season-$cur_ep_obj.season">
|
||||
<td colspan="4" class="text-left">
|
||||
<h2>#if 0 == int($cur_ep_obj.season) then 'Specials' else 'Season %s' % $cur_ep_obj.season#</h2>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="seasoncols" id="season-$cur_ep_obj.season-cols">
|
||||
<th class="col-checkbox"><input type="checkbox" class="seasonCheck" id="$cur_ep_obj.season" /></th>
|
||||
<th class="text-nowrap">Episode</th>
|
||||
<th class="col-name">Old Location</th>
|
||||
<th class="col-name">New Location</th>
|
||||
</tr>
|
||||
</thead>
|
||||
#set $curSeason = int($cur_ep_obj.season)
|
||||
|
||||
#if $curSeason != int($cur_ep_obj.season):
|
||||
#set $curSeason = int($cur_ep_obj.season)
|
||||
#if not $first_season
|
||||
</tbody>
|
||||
#end if
|
||||
#set $first_season = False
|
||||
<thead>
|
||||
<tr class="seasonheader" id="season-$cur_ep_obj.season">
|
||||
<td colspan="3" class="text-left">
|
||||
<h2>#if 0 == int($cur_ep_obj.season) then 'Specials' else 'Season %s' % $cur_ep_obj.season#</h2>
|
||||
</td>
|
||||
</tr>
|
||||
<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="text-nowrap">Episode</th>
|
||||
<th class="col-name">Old Location / New Location</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
#end if
|
||||
##
|
||||
#set $odd = not $odd
|
||||
#set $epStr = str($cur_ep_obj.season) + 'x' + str($cur_ep_obj.episode)
|
||||
#set $curLoc = $cur_ep_obj.location[len($cur_ep_obj.show.location) + 1:]
|
||||
#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])
|
||||
#if 1 < len($epList)
|
||||
#set $epList = [$min($epList), $max($epList)]
|
||||
#end if
|
||||
<tbody>
|
||||
<tr class="season-$curSeason #if $curLoc == $newLoc#good#else#wanted#end if# seasonstyle">
|
||||
#if $curLoc != $newLoc
|
||||
<td class="col-checkbox">
|
||||
<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) %>">
|
||||
</td>
|
||||
#else
|
||||
<td></td>
|
||||
#end if
|
||||
<td class="col-ep text-nowrap"><%= '-'.join(map(str, epList)) %></td>
|
||||
<td class="col-name text-left">$curLoc</td>
|
||||
<td class="col-name text-left">$newLoc</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tr class="opacity60 #if $curLoc == $newLoc#good#else#wanted#end if#">
|
||||
#if $curLoc != $newLoc
|
||||
#set $epStr = '%sx%s' % ($cur_ep_obj.season, $cur_ep_obj.episode)
|
||||
<td class="col-checkbox" rowspan="2" style="line-height:30px">
|
||||
<input type="checkbox" class="epCheck" id="$epStr" name="$epStr">
|
||||
</td>
|
||||
#else
|
||||
<td rowspan="2"> </td>
|
||||
#end if
|
||||
<td class="col-ep text-nowrap" rowspan="2">#echo '-'.join(map(str, epList))#</td>
|
||||
<td style="text-align:left">now: $curLoc.replace('/', '/ ').replace('\\', ' \\ ')</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>
|
||||
#end for
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</table>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<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>
|
||||
</div>
|
||||
|
||||
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_bottom.tmpl')
|
||||
|
|
|
@ -2,28 +2,35 @@
|
|||
#from sickbeard import classes
|
||||
#from sickbeard.common import *
|
||||
#from sickbeard.logger import reverseNames
|
||||
#from sickbeard.helpers import maybe_plural
|
||||
##
|
||||
#set global $header = 'Log File'
|
||||
#set global $title = 'Logs'
|
||||
#set global $sbPath = '..'
|
||||
#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
|
||||
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_top.tmpl')
|
||||
|
||||
#if $varExists('header')
|
||||
<h1 class="header">$header</h1>
|
||||
#else
|
||||
#else
|
||||
<h1 class="title">$title</h1>
|
||||
#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">
|
||||
#set $levels = $reverseNames.keys()
|
||||
#set void = $levels.sort(lambda x,y: cmp($reverseNames[$x], $reverseNames[$y]))
|
||||
#set $level_count = len($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
|
||||
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
@ -35,7 +42,7 @@
|
|||
<!--
|
||||
\$(document).ready(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
|
||||
|
@ -43,4 +50,4 @@
|
|||
//-->
|
||||
</script>
|
||||
|
||||
#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')
|
||||
|
|
|
@ -468,7 +468,7 @@ $(document).ready(function () {
|
|||
at: 'top center'
|
||||
},
|
||||
style: {
|
||||
classes: 'qtip-rounded qtip-shadow'
|
||||
classes: 'qtip-dark qtip-rounded qtip-shadow'
|
||||
}
|
||||
});
|
||||
$('.custom-pattern,#unpack').qtip({
|
||||
|
|
|
@ -40,7 +40,6 @@ $(document).ready(function(){
|
|||
$.getJSON(sbRoot + '/config/providers/getNewznabCategories', params,
|
||||
function(data){
|
||||
updateNewznabCaps( data, selectedProvider );
|
||||
//console.debug(data.tv_categories);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -217,7 +216,6 @@ $(document).ready(function(){
|
|||
if (rootObject.name == searchFor) {
|
||||
found = true;
|
||||
}
|
||||
//console.log(rootObject.name + ' while searching for: ' + searchFor);
|
||||
});
|
||||
return found;
|
||||
};
|
||||
|
@ -247,20 +245,20 @@ $(document).ready(function(){
|
|||
$.fn.newznabProvidersCapabilities.forEach(function (newzNabCap) {
|
||||
$.sgd && console.log('array found:' + (newzNabCap.categories instanceof Array ? 'yes': 'no'));
|
||||
|
||||
if (newzNabCap.name && newzNabCap.name == selectedProvider[0] && newzNabCap.categories instanceof Array) {
|
||||
if (newzNabCap.name && newzNabCap.name == selectedProvider[0] && newzNabCap.categories instanceof Array) {
|
||||
newzNabCap.categories.forEach(function (category_set) {
|
||||
if (category_set.id && category_set.name) {
|
||||
catName = category_set.name.replace(/Docu([^\w]|$)(.*?)/i, 'Documentary$1');
|
||||
newCapOptions.push({
|
||||
value: category_set.id,
|
||||
text: catName + ' (' + category_set.id + ')'
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
$('#newznab_cap').replaceOptions(newCapOptions);
|
||||
hasCats = !!newCapOptions.length
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
$('#nn-loadcats').removeClass('show').addClass('hide');
|
||||
if (hasCats) {
|
||||
$.sgd && console.log('hasCats');
|
||||
|
@ -270,7 +268,7 @@ $(document).ready(function(){
|
|||
$.sgd && console.log('noCats');
|
||||
$('#nn-cats').removeClass('show').addClass('hide');
|
||||
$('#nn-nocats').removeClass('hide').addClass('show');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$.sgd && console.log('errCats');
|
||||
// error - no caps
|
||||
|
@ -412,7 +410,6 @@ $(document).ready(function(){
|
|||
});
|
||||
|
||||
$(this).on('click', '#newznab_cat_update', function(){
|
||||
//console.debug('Clicked Button');
|
||||
|
||||
//Maybe check if there is anything selected?
|
||||
$('#newznab_cat option').each(function() {
|
||||
|
@ -428,7 +425,6 @@ $(document).ready(function(){
|
|||
if($(this).attr('selected') == 'selected')
|
||||
{
|
||||
var selected_cat = $(this).val();
|
||||
//console.debug(selected_cat);
|
||||
newOptions.push({text: selected_cat, value: selected_cat})
|
||||
};
|
||||
});
|
||||
|
|
|
@ -1,264 +1,317 @@
|
|||
$(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 () {
|
||||
var id = $(this).val();
|
||||
if (id && id != 'jump') {
|
||||
$('html,body').animate({scrollTop: $(id).offset().top}, 'slow');
|
||||
location.hash = id;
|
||||
}
|
||||
$(this).val('jump');
|
||||
});
|
||||
$('#seasonJump').change(function() {
|
||||
var id = $(this).val();
|
||||
if (id && 'jump' != id) {
|
||||
$('html,body').animate({scrollTop: $(id).offset().top}, 'slow');
|
||||
location.hash = id;
|
||||
}
|
||||
$(this).val('jump');
|
||||
});
|
||||
|
||||
$('#prevShow, #nextShow').click(function () {
|
||||
var select$ = $('#pickShow'),
|
||||
index = $.inArray(select$.find('option:selected').val()*1, TVShowList);
|
||||
select$.find('option[value="' + TVShowList[('nextShow' === $(this).attr('id')
|
||||
? (index < TVShowList.length - 1 ? index + 1 : 0)
|
||||
: (0 < index ? index - 1 : TVShowList.length - 1))] + '"]').attr('selected', 'selected');
|
||||
select$.change();
|
||||
return false;
|
||||
});
|
||||
$('.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'
|
||||
});
|
||||
|
||||
$('#changeStatus').click(function () {
|
||||
var sbRoot = $('#sbRoot').val();
|
||||
var epArr = new Array()
|
||||
if (config.useIMDbInfo){
|
||||
$.fn.generateStars = function() {
|
||||
return this.each(function(i,e){$(e).html($('<span/>').width($(e).text()*12));});
|
||||
};
|
||||
$('.imdbstars').generateStars();
|
||||
}
|
||||
|
||||
$('.epCheck').each(function () {
|
||||
$('#changeStatus').on('click', function() {
|
||||
var epArr = [];
|
||||
|
||||
if (this.checked == true) {
|
||||
epArr.push($(this).attr('id'))
|
||||
}
|
||||
$('.epCheck').each(function() {
|
||||
this.checked && epArr.push($(this).attr('id'))
|
||||
});
|
||||
if (epArr.length)
|
||||
window.location.href = $.SickGear.Root + '/home/setStatus?show=' + $('#showID').attr('value') +
|
||||
'&eps=' + epArr.join('|') + '&status=' + $('#statusSelect').attr('value');
|
||||
});
|
||||
|
||||
});
|
||||
// show/hide different types of rows when the checkboxes are changed
|
||||
var el = $('#checkboxControls').find('input');
|
||||
el.change(function() {
|
||||
$(this).showHideRows($(this).attr('id'));
|
||||
});
|
||||
|
||||
if (epArr.length == 0)
|
||||
return false;
|
||||
// initially show/hide all the rows according to the checkboxes
|
||||
el.each(function() {
|
||||
var status = this.checked;
|
||||
$('tr.' + $(this).attr('id')).each(function() {
|
||||
status && $(this).show() || $(this).hide();
|
||||
});
|
||||
});
|
||||
|
||||
url = sbRoot + '/home/setStatus?show=' + $('#showID').attr('value') + '&eps=' + epArr.join('|') + '&status=' + $('#statusSelect').attr('value');
|
||||
window.location.href = url
|
||||
$.fn.showHideRows = function(whichClass) {
|
||||
|
||||
});
|
||||
var status = $('#checkboxControls > input, #' + whichClass).prop('checked');
|
||||
$('tr.' + whichClass).each(function() {
|
||||
status && $(this).show() || $(this).hide();
|
||||
});
|
||||
|
||||
$('.seasonCheck').click(function () {
|
||||
var seasCheck = this;
|
||||
var seasNo = $(seasCheck).attr('id');
|
||||
// hide season headers with no episodes under them
|
||||
$('tr.seasonheader').each(function() {
|
||||
var numRows = 0;
|
||||
var seasonNo = $(this).attr('id');
|
||||
$('tr.' + seasonNo + ' :visible').each(function() {
|
||||
numRows++
|
||||
});
|
||||
var el = $('#' + seasonNo + '-cols');
|
||||
if (0 == numRows) {
|
||||
$(this).hide();
|
||||
el.hide();
|
||||
} else {
|
||||
$(this).show();
|
||||
el.show();
|
||||
}
|
||||
|
||||
$('.epCheck:visible').each(function () {
|
||||
var epParts = $(this).attr('id').split('x');
|
||||
});
|
||||
};
|
||||
|
||||
if (epParts[0] == seasNo) {
|
||||
this.checked = seasCheck.checked
|
||||
}
|
||||
});
|
||||
});
|
||||
function checkState(state){
|
||||
$('.epCheck:visible, .seasonCheck:visible').prop('checked', state)
|
||||
}
|
||||
// selects all visible episode checkboxes.
|
||||
$('.seriesCheck').on('click', function() { checkState(!0); });
|
||||
|
||||
var lastCheck = null;
|
||||
$('.epCheck').click(function (event) {
|
||||
// clears all visible episode checkboxes and the season selectors
|
||||
$('.clearAll').on('click', function() { checkState(!1); });
|
||||
|
||||
if (!lastCheck || !event.shiftKey) {
|
||||
lastCheck = this;
|
||||
return;
|
||||
}
|
||||
function setEpisodeSceneNumbering(forSeason, forEpisode, sceneSeason, sceneEpisode) {
|
||||
var showId = $('#showID').val(), indexer = $('#indexer').val();
|
||||
|
||||
var check = this;
|
||||
var found = 0;
|
||||
if ('' === sceneSeason) sceneSeason = null;
|
||||
if ('' === sceneEpisode) sceneEpisode = null;
|
||||
|
||||
$('.epCheck').each(function () {
|
||||
switch (found) {
|
||||
case 2:
|
||||
return false;
|
||||
case 1:
|
||||
this.checked = lastCheck.checked;
|
||||
}
|
||||
$.getJSON($.SickGear.Root + '/home/setSceneNumbering',
|
||||
{
|
||||
'show': showId,
|
||||
'indexer': indexer,
|
||||
'forSeason': forSeason,
|
||||
'forEpisode': forEpisode,
|
||||
'sceneSeason': sceneSeason,
|
||||
'sceneEpisode': sceneEpisode
|
||||
},
|
||||
function(data) {
|
||||
// Set the values we get back
|
||||
$('#sceneSeasonXEpisode_' + showId + '_' + forSeason + '_' + forEpisode).val(
|
||||
(null === data.sceneSeason || null === data.sceneEpisode)
|
||||
? '' : data.sceneSeason + 'x' + data.sceneEpisode);
|
||||
if (!data.success)
|
||||
alert(data.errorMessage ? data.errorMessage : 'Update failed.');
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (this == check || this == lastCheck)
|
||||
found++;
|
||||
});
|
||||
function setAbsoluteSceneNumbering(forAbsolute, sceneAbsolute) {
|
||||
var showId = $('#showID').val(), indexer = $('#indexer').val();
|
||||
|
||||
lastClick = this;
|
||||
});
|
||||
if ('' === sceneAbsolute)
|
||||
sceneAbsolute = null;
|
||||
|
||||
// selects all visible episode checkboxes.
|
||||
$('.seriesCheck').click(function () {
|
||||
$('.epCheck:visible').each(function () {
|
||||
this.checked = true
|
||||
});
|
||||
$('.seasonCheck:visible').each(function () {
|
||||
this.checked = true
|
||||
})
|
||||
});
|
||||
$.getJSON($.SickGear.Root + '/home/setSceneNumbering',
|
||||
{
|
||||
'show': showId,
|
||||
'indexer': indexer,
|
||||
'forAbsolute': forAbsolute,
|
||||
'sceneAbsolute': sceneAbsolute
|
||||
},
|
||||
function(data) {
|
||||
// Set the values we get back
|
||||
$('#sceneAbsolute_' + showId + '_' + forAbsolute).val(
|
||||
(null === data.sceneAbsolute) ? '' : data.sceneAbsolute);
|
||||
if (!data.success)
|
||||
alert(data.errorMessage ? data.errorMessage : 'Update failed.');
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// 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
|
||||
});
|
||||
});
|
||||
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'));
|
||||
|
||||
// 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
|
||||
});
|
||||
function table_init(table$) {
|
||||
$('#sbRoot').ajaxEpSearch({'colorRow': true});
|
||||
$('#sbRoot').ajaxEpSubtitlesSearch();
|
||||
|
||||
// show/hide different types of rows when the checkboxes are changed
|
||||
$("#checkboxControls input").change(function (e) {
|
||||
var whichClass = $(this).attr('id');
|
||||
$(this).showHideRows(whichClass);
|
||||
});
|
||||
if ($.SickGear.config.useFuzzy) {
|
||||
fuzzyMoment({
|
||||
containerClass: '.airdate',
|
||||
dateHasTime: !1,
|
||||
dateFormat: $.SickGear.config.dateFormat,
|
||||
timeFormat: $.SickGear.config.timeFormat,
|
||||
trimZero: $.SickGear.config.fuzzyTrimZero
|
||||
});
|
||||
}
|
||||
|
||||
// initially show/hide all the rows according to the checkboxes
|
||||
$("#checkboxControls input").each(function (e) {
|
||||
var status = this.checked;
|
||||
$("tr." + $(this).attr('id')).each(function (e) {
|
||||
if (status) {
|
||||
$(this).show();
|
||||
} else {
|
||||
$(this).hide();
|
||||
}
|
||||
});
|
||||
});
|
||||
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'}
|
||||
}
|
||||
});
|
||||
|
||||
$.fn.showHideRows = function (whichClass) {
|
||||
$(obj).find('.seasonCheck').on('click', function() {
|
||||
var seasCheck = this, seasNo = $(seasCheck).attr('id');
|
||||
|
||||
var status = $('#checkboxControls > input, #' + whichClass).prop('checked');
|
||||
$("tr." + whichClass).each(function (e) {
|
||||
if (status) {
|
||||
$(this).show();
|
||||
} else {
|
||||
$(this).hide();
|
||||
}
|
||||
});
|
||||
$(obj).find('.epCheck:visible').each(function() {
|
||||
var epParts = $(this).attr('id').split('x');
|
||||
if (epParts[0] == seasNo)
|
||||
this.checked = seasCheck.checked
|
||||
|
||||
// hide season headers with no episodes under them
|
||||
$('tr.seasonheader').each(function () {
|
||||
var numRows = 0;
|
||||
var seasonNo = $(this).attr('id');
|
||||
$('tr.' + seasonNo + ' :visible').each(function () {
|
||||
numRows++
|
||||
});
|
||||
if (numRows == 0) {
|
||||
$(this).hide();
|
||||
$('#' + seasonNo + '-cols').hide()
|
||||
} else {
|
||||
$(this).show();
|
||||
$('#' + seasonNo + '-cols').show()
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
};
|
||||
var lastCheck = null;
|
||||
$(obj).find('.epCheck').on('click', function(event) {
|
||||
|
||||
function setEpisodeSceneNumbering(forSeason, forEpisode, sceneSeason, sceneEpisode) {
|
||||
var sbRoot = $('#sbRoot').val();
|
||||
var showId = $('#showID').val();
|
||||
var indexer = $('#indexer').val();
|
||||
if (!lastCheck || !event.shiftKey) {
|
||||
lastCheck = this;
|
||||
return;
|
||||
}
|
||||
|
||||
if (sceneSeason === '') sceneSeason = null;
|
||||
if (sceneEpisode === '') sceneEpisode = null;
|
||||
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;
|
||||
});
|
||||
|
||||
$.getJSON(sbRoot + '/home/setSceneNumbering',
|
||||
{
|
||||
'show': showId,
|
||||
'indexer': indexer,
|
||||
'forSeason': forSeason,
|
||||
'forEpisode': forEpisode,
|
||||
'sceneSeason': sceneSeason,
|
||||
'sceneEpisode': sceneEpisode
|
||||
},
|
||||
function (data) {
|
||||
// Set the values we get back
|
||||
if (data.sceneSeason === null || data.sceneEpisode === null) {
|
||||
$('#sceneSeasonXEpisode_' + showId + '_' + forSeason + '_' + forEpisode).val('');
|
||||
}
|
||||
else {
|
||||
$('#sceneSeasonXEpisode_' + showId + '_' + forSeason + '_' + forEpisode).val(data.sceneSeason + 'x' + data.sceneEpisode);
|
||||
}
|
||||
if (!data.success) {
|
||||
if (data.errorMessage) {
|
||||
alert(data.errorMessage);
|
||||
} else {
|
||||
alert('Update failed.');
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
qTips($(obj).find('.addQTip'));
|
||||
plotter($(obj).find('.plotInfo'));
|
||||
|
||||
function setAbsoluteSceneNumbering(forAbsolute, sceneAbsolute) {
|
||||
var sbRoot = $('#sbRoot').val();
|
||||
var showId = $('#showID').val();
|
||||
var indexer = $('#indexer').val();
|
||||
$(obj).find('.sceneSeasonXEpisode').change(function() {
|
||||
// Strip non-numeric characters
|
||||
$(this).val($(this).val().replace(/[^0-9xX]*/g, ''));
|
||||
|
||||
if (sceneAbsolute === '') sceneAbsolute = null;
|
||||
var forSeason = $(this).attr('data-for-season'),
|
||||
forEpisode = $(this).attr('data-for-episode'),
|
||||
m = $(this).val().match(/^(\d+)x(\d+)$/i),
|
||||
sceneSeason = m && m[1] || null, sceneEpisode = m && m[2] || null;
|
||||
|
||||
$.getJSON(sbRoot + '/home/setSceneNumbering',
|
||||
{
|
||||
'show': showId,
|
||||
'indexer': indexer,
|
||||
'forAbsolute': forAbsolute,
|
||||
'sceneAbsolute': sceneAbsolute
|
||||
},
|
||||
function (data) {
|
||||
// Set the values we get back
|
||||
if (data.sceneAbsolute === null) {
|
||||
$('#sceneAbsolute_' + showId + '_' + forAbsolute).val('');
|
||||
}
|
||||
else {
|
||||
$('#sceneAbsolute_' + showId + '_' + forAbsolute).val(data.sceneAbsolute);
|
||||
}
|
||||
if (!data.success) {
|
||||
if (data.errorMessage) {
|
||||
alert(data.errorMessage);
|
||||
} else {
|
||||
alert('Update failed.');
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
setEpisodeSceneNumbering(forSeason, forEpisode, sceneSeason, sceneEpisode);
|
||||
});
|
||||
|
||||
$('.sceneSeasonXEpisode').change(function () {
|
||||
// Strip non-numeric characters
|
||||
$(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();
|
||||
$(obj).find('.sceneAbsolute').change(function() {
|
||||
// Strip non-numeric characters
|
||||
$(this).val($(this).val().replace(/[^0-9xX]*/g, ''));
|
||||
|
||||
//var sceneEpisode = $('#sceneEpisode_' + showId + '_' + forSeason +'_' + forEpisode).val();
|
||||
var m = $(this).val().match(/^(\d+)x(\d+)$/i);
|
||||
var sceneSeason = null, sceneEpisode = null;
|
||||
if (m) {
|
||||
sceneSeason = m[1];
|
||||
sceneEpisode = m[2];
|
||||
}
|
||||
setEpisodeSceneNumbering(forSeason, forEpisode, sceneSeason, sceneEpisode);
|
||||
});
|
||||
var forAbsolute = $(this).attr('data-for-absolute'),
|
||||
m = $(this).val().match(/^(\d{1,3})$/i),
|
||||
sceneAbsolute = m && m[1] || null;
|
||||
|
||||
$('.sceneAbsolute').change(function () {
|
||||
// Strip non-numeric characters
|
||||
$(this).val($(this).val().replace(/[^0-9xX]*/g, ''));
|
||||
var forAbsolute = $(this).attr('data-for-absolute');
|
||||
var showId = $('#showID').val();
|
||||
var indexer = $('#indexer').val();
|
||||
setAbsoluteSceneNumbering(forAbsolute, sceneAbsolute);
|
||||
});
|
||||
});
|
||||
}
|
||||
table_init($('.sickbeardTable'));
|
||||
|
||||
var m = $(this).val().match(/^(\d{1,3})$/i);
|
||||
var sceneAbsolute = null;
|
||||
if (m) {
|
||||
sceneAbsolute = m[1];
|
||||
}
|
||||
setAbsoluteSceneNumbering(forAbsolute, sceneAbsolute);
|
||||
});
|
||||
$.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;
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/** @namespace $.SickGear.Root */
|
||||
/** @namespace config.showLang */
|
||||
/** @namespace config.showIsAnime */
|
||||
/*globals $, config, sbRoot, generate_bwlist*/
|
||||
|
@ -7,13 +8,13 @@ $(document).ready(function () {
|
|||
$('#location').fileBrowser({title: 'Select Show Location'});
|
||||
|
||||
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"';
|
||||
|
||||
if (0 == data.results.length) {
|
||||
if (!data.results.length) {
|
||||
result = '<option value="' + config.showLang + '"' + selected + htmlFlag(config.showLang) + '>'
|
||||
+ config.showLang + '</option>';
|
||||
} else {
|
||||
|
@ -47,13 +48,13 @@ $(document).ready(function () {
|
|||
return allExceptions
|
||||
}
|
||||
|
||||
$('#submit').click(function () {
|
||||
$('#submit').on('click', function () {
|
||||
$('#exceptions_list').val(getExceptions());
|
||||
if (config.showIsAnime)
|
||||
generate_bwlist();
|
||||
});
|
||||
|
||||
$('#addSceneName').click(function () {
|
||||
$('#addSceneName').on('click', function () {
|
||||
var elSceneName = $('#SceneName'), elSceneNameSeason = $('#SceneNameSeason'),
|
||||
sceneEx = elSceneName.val(), sceneExSeason = elSceneNameSeason.val();
|
||||
|
||||
|
@ -72,7 +73,7 @@ $(document).ready(function () {
|
|||
return option.appendTo($('#exceptions_list'));
|
||||
});
|
||||
|
||||
$('#removeSceneName').click(function () {
|
||||
$('#removeSceneName').on('click', function () {
|
||||
$('#exceptions_list').find('option:selected').remove();
|
||||
|
||||
$(this).toggle_SceneException();
|
||||
|
@ -99,8 +100,8 @@ $(document).ready(function () {
|
|||
uncheck(elABD); uncheck(elSports);
|
||||
if (config.showIsAnime) { $('#blackwhitelist').fadeIn('fast', 'linear'); } return !0; }
|
||||
function isScene() { uncheck(elABD); uncheck(elSports); }
|
||||
function isABD() { uncheck(elAnime); uncheck(elScene); $('#blackwhitelist').fadeOut('fast', 'linear'); }
|
||||
function isSports() { 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, #anime-options').fadeOut('fast', 'linear'); }
|
||||
|
||||
if (checked(elAnime)) { isAnime(); }
|
||||
if (checked(elScene)) { isScene(); }
|
||||
|
|
|
@ -21,7 +21,6 @@ function initActions() {
|
|||
$('#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("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("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');
|
||||
|
@ -40,4 +39,5 @@ $(document).ready(function(){
|
|||
initActions();
|
||||
$('#NAV' + topmenu).addClass('active');
|
||||
$('.dropdown-toggle').dropdownHover();
|
||||
(/undefined/i.test(document.createElement('input').placeholder)) && $('body').addClass('no-placeholders');
|
||||
});
|
||||
|
|
2
gui/slick/js/lib/jquery.collapser.min.js
vendored
|
@ -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]")),
|
||||
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",
|
||||
"");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]?
|
||||
" "+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);
|
|
@ -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).
|
||||
setting: {startline:100, scrollto: 0, scrollduration:1000, fadeduration:[500, 100]},
|
||||
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
|
||||
|
||||
state: {isvisible:false, shouldvisible:false},
|
||||
|
@ -56,7 +56,7 @@ var scrolltotop={
|
|||
mainobj.$body=(window.opera)? (document.compatMode=="CSS1Compat"? $('html') : $('body')) : $('html,body')
|
||||
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'})
|
||||
.attr({title:'Scroll Back to Top'})
|
||||
.attr({title:'Scroll to Top'})
|
||||
.click(function(){mainobj.scrollup(); return false})
|
||||
.appendTo('body')
|
||||
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
|
@ -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();
|
||||
|
||||
});
|
|
@ -1,46 +1,47 @@
|
|||
$(function () {
|
||||
$('.plotInfo, .plot-daybyday').each(function () {
|
||||
var match = $(this).attr('id').match(/^plot(?:_info_|-)((\d+)_(\d+)[_x](\d+))$/);
|
||||
var showName = $('#show-' + match[1]).attr('data-rawname');
|
||||
$(this).qtip({
|
||||
content: {
|
||||
text: function(event, api) {
|
||||
// deferred object ensuring the request is only made once
|
||||
$.ajax({
|
||||
url: $('#sbRoot').val() + '/home/plotDetails',
|
||||
type: 'GET',
|
||||
data: {
|
||||
show: match[2],
|
||||
episode: match[4],
|
||||
season: match[3]
|
||||
}
|
||||
})
|
||||
.then(function(content) {
|
||||
// Set the tooltip content upon successful retrieval
|
||||
api.set('content.text', ('undefined' === typeof(showName) ? ''
|
||||
: ('' !== content ? '<b class="boldest">' + showName + '</b>' : showName))
|
||||
+ ('' !== content ? ' ' + content : ''));
|
||||
}, function(xhr, status, error) {
|
||||
// Upon failure... set the tooltip content to the status and error value
|
||||
api.set('content.text', status + ': ' + error);
|
||||
});
|
||||
return 'Loading...'; // Set initial text
|
||||
}
|
||||
},
|
||||
show: {
|
||||
solo: true
|
||||
},
|
||||
position: {
|
||||
viewport: $(window),
|
||||
my: 'left center',
|
||||
adjust: {
|
||||
y: -10,
|
||||
x: 0
|
||||
}
|
||||
},
|
||||
style: {
|
||||
classes: 'qtip-rounded qtip-shadow'
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
var plotter = function(select$) {
|
||||
select$.each(function() {
|
||||
var match = $(this).attr('id').match(/^plot(?:_info_|-)((\d+)_(\d+)[_x](\d+))$/);
|
||||
var showName = $('#show-' + match[1]).attr('data-rawname');
|
||||
$(this).qtip({
|
||||
content: {
|
||||
text: function(event, api) {
|
||||
// deferred object ensuring the request is only made once
|
||||
$.ajax({
|
||||
url: $.SickGear.Root + '/home/plotDetails',
|
||||
type: 'GET',
|
||||
data: {
|
||||
show: match[2],
|
||||
episode: match[4],
|
||||
season: match[3]
|
||||
}
|
||||
})
|
||||
.then(function(content) {
|
||||
// Set the tooltip content upon successful retrieval
|
||||
api.set('content.text', ('undefined' === typeof(showName) ? ''
|
||||
: ('' !== content ? '<b class="boldest">' + showName + '</b>' : showName))
|
||||
+ ('' !== content ? ' ' + content : ''));
|
||||
}, function(xhr, status, error) {
|
||||
// Upon failure... set the tooltip content to the status and error value
|
||||
api.set('content.text', status + ': ' + error);
|
||||
});
|
||||
return 'Loading...'; // Set initial text
|
||||
}
|
||||
},
|
||||
show: {
|
||||
solo: true
|
||||
},
|
||||
position: {
|
||||
viewport: $(window),
|
||||
my: 'left center',
|
||||
adjust: {
|
||||
y: -10,
|
||||
x: 0
|
||||
}
|
||||
},
|
||||
style: {
|
||||
classes: 'qtip-dark qtip-rounded qtip-shadow'
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
$(function () { plotter($('.plotInfo, .plot-daybyday')) });
|
||||
|
|
|
@ -19,7 +19,7 @@ $(function () {
|
|||
}
|
||||
},
|
||||
style: {
|
||||
classes: 'qtip-rounded qtip-shadow'
|
||||
classes: 'qtip-dark qtip-rounded qtip-shadow'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -6,7 +6,7 @@ $(function () {
|
|||
text: function(event, api) {
|
||||
// deferred object ensuring the request is only made once
|
||||
$.ajax({
|
||||
url: $('#sbRoot').val() + '/home/sceneExceptions',
|
||||
url: $.SickGear.Root + '/home/sceneExceptions',
|
||||
type: 'GET',
|
||||
data: {
|
||||
show: match[1]
|
||||
|
@ -35,7 +35,7 @@ $(function () {
|
|||
}
|
||||
},
|
||||
style: {
|
||||
classes: 'qtip-rounded qtip-shadow'
|
||||
classes: 'qtip-dark qtip-rounded qtip-shadow'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
98
lib/fanart/__init__.py
Normal 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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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),
|
||||
)
|
|
@ -19,26 +19,24 @@ class TMDB:
|
|||
url = TMDB.url + '/' + path + '?api_key=' + TMDB.api_key
|
||||
if method == 'GET':
|
||||
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':
|
||||
for key in params.keys():
|
||||
url += '&' + key + '=' + params[key]
|
||||
headers = {'Content-Type': 'application/json', \
|
||||
'Accept': 'application/json'}
|
||||
content = requests.post(url, data=json.dumps(json_body), \
|
||||
headers=headers).content
|
||||
content = requests.post(url, data=json.dumps(json_body), headers=headers, verify=False).content
|
||||
elif method == 'DELETE':
|
||||
for key in params.keys():
|
||||
url += '&' + key + '=' + params[key]
|
||||
headers = {'Content-Type': 'application/json', \
|
||||
'Accept': 'application/json'}
|
||||
content = requests.delete(url, data=json.dumps(json_body), \
|
||||
headers=headers).content
|
||||
content = requests.delete(url, data=json.dumps(json_body), headers=headers, verify=False).content
|
||||
else:
|
||||
raise Exception('method: ' + method + ' not supported.')
|
||||
response = json.loads(content.decode('utf-8'))
|
||||
return response
|
||||
|
||||
|
||||
#
|
||||
# Set attributes to dictionary values.
|
||||
# - e.g.
|
||||
|
@ -81,7 +79,7 @@ class TMDB:
|
|||
response = TMDB._request('GET', path, params)
|
||||
TMDB._set_attrs_to_values(self, response)
|
||||
return response
|
||||
|
||||
|
||||
# optional parameters: page, language
|
||||
def lists(self, params={}):
|
||||
path = 'account' + '/' + str(self.session_id) + '/lists'
|
||||
|
@ -121,7 +119,7 @@ class TMDB:
|
|||
response = TMDB._request('GET', path, params)
|
||||
TMDB._set_attrs_to_values(self, response)
|
||||
return response
|
||||
|
||||
|
||||
# required JSON body: movie_id, movie_watchlist
|
||||
def movie_watchlist_post(self, json_body):
|
||||
path = 'account' + '/' + str(json_body['movie_id']) + \
|
||||
|
@ -175,7 +173,7 @@ class TMDB:
|
|||
response = TMDB._request('GET', path, params)
|
||||
TMDB._set_attrs_to_values(self, response)
|
||||
return response
|
||||
|
||||
|
||||
# optional parameters: page, start_date, end_date
|
||||
def person(self, params={}):
|
||||
path = 'person/changes'
|
||||
|
@ -218,7 +216,7 @@ class TMDB:
|
|||
response = TMDB._request('GET', path)
|
||||
TMDB._set_attrs_to_values(self, response)
|
||||
return response
|
||||
|
||||
|
||||
# optional parameters: page, language
|
||||
def movies(self, params={}):
|
||||
path = 'company' + '/' + str(self.id) + '/movies'
|
||||
|
@ -249,9 +247,9 @@ class TMDB:
|
|||
def __init__(self):
|
||||
pass
|
||||
|
||||
# optional parameters: page, language, sort_by, include_adult, year,
|
||||
# primary_release_year, vote_count.gte, vote_average.gte, with_genres,
|
||||
# release_date.gte, release_date.lte, certification_country,
|
||||
# optional parameters: page, language, sort_by, include_adult, year,
|
||||
# primary_release_year, vote_count.gte, vote_average.gte, with_genres,
|
||||
# release_date.gte, release_date.lte, certification_country,
|
||||
# certification.lte, with_companies
|
||||
def movie(self, params):
|
||||
path = 'discover/movie'
|
||||
|
@ -297,7 +295,7 @@ class TMDB:
|
|||
response = TMDB._request('GET', path, params)
|
||||
TMDB._set_attrs_to_values(self, response)
|
||||
return response
|
||||
|
||||
|
||||
# optional parameters: page, language, include_all_movies, include_adult
|
||||
def movies(self, params={}):
|
||||
path = 'genre' + '/' + str(self.id) + '/movies'
|
||||
|
@ -318,7 +316,7 @@ class TMDB:
|
|||
response = TMDB._request('GET', path)
|
||||
TMDB._set_attrs_to_values(self, response)
|
||||
return response
|
||||
|
||||
|
||||
#
|
||||
# Keywords
|
||||
# http://docs.themoviedb.apiary.io/#keywords
|
||||
|
@ -378,7 +376,7 @@ class TMDB:
|
|||
response = TMDB._request('POST', path, params, json_body)
|
||||
TMDB._set_attrs_to_values(self, response)
|
||||
return response
|
||||
|
||||
|
||||
# required JSON body: media_id
|
||||
def remove_item(self, json_body):
|
||||
path = 'list' + '/' + str(self.id) + '/remove_item'
|
||||
|
@ -460,21 +458,21 @@ class TMDB:
|
|||
response = TMDB._request('GET', path, params)
|
||||
TMDB._set_attrs_to_values(self, response)
|
||||
return response
|
||||
|
||||
|
||||
# optional parameters: page, language
|
||||
def reviews(self, params={}):
|
||||
path = 'movie' + '/' + str(self.id) + '/reviews'
|
||||
response = TMDB._request('GET', path, params)
|
||||
TMDB._set_attrs_to_values(self, response)
|
||||
return response
|
||||
|
||||
|
||||
# optional parameters: page, language
|
||||
def lists(self, params={}):
|
||||
path = 'movie' + '/' + str(self.id) + '/lists'
|
||||
response = TMDB._request('GET', path, params)
|
||||
TMDB._set_attrs_to_values(self, response)
|
||||
return response
|
||||
|
||||
|
||||
# optional parameters: start_date, end_date
|
||||
def changes(self, params={}):
|
||||
path = 'movie' + '/' + str(self.id) + '/changes'
|
||||
|
@ -501,7 +499,7 @@ class TMDB:
|
|||
response = TMDB._request('GET', path, params)
|
||||
TMDB._set_attrs_to_values(self, response)
|
||||
return response
|
||||
|
||||
|
||||
# optional parameters: page, language
|
||||
def popular(self, params={}):
|
||||
path = 'movie/popular'
|
||||
|
@ -629,7 +627,7 @@ class TMDB:
|
|||
pass
|
||||
|
||||
# required parameters: query
|
||||
# optional parameters: page, language, include_adult, year,
|
||||
# optional parameters: page, language, include_adult, year,
|
||||
# primary_release_year, search_type
|
||||
def movie(self, params):
|
||||
path = 'search/movie'
|
||||
|
@ -699,7 +697,7 @@ class TMDB:
|
|||
response = TMDB._request('GET', path, params)
|
||||
TMDB._set_attrs_to_values(self, response)
|
||||
return response
|
||||
|
||||
|
||||
# optional parameter: language
|
||||
def credits(self, params={}):
|
||||
path = 'tv' + '/' + str(self.id) + '/credits'
|
||||
|
|
|
@ -35,7 +35,7 @@ import uuid
|
|||
|
||||
sys.path.insert(1, os.path.abspath('../lib'))
|
||||
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, \
|
||||
show_queue, show_updater, subtitles, traktChecker, version_checker, indexermapper, classes
|
||||
from sickbeard.config import CheckSection, check_setting_int, check_setting_str, ConfigMigrator, minimax
|
||||
|
@ -423,13 +423,28 @@ EMAIL_LIST = None
|
|||
|
||||
GUI_NAME = None
|
||||
DEFAULT_HOME = None
|
||||
FANART_LIMIT = None
|
||||
FANART_PANEL = None
|
||||
FANART_RATINGS = {}
|
||||
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
|
||||
EPISODE_VIEW_VIEWMODE = 0
|
||||
EPISODE_VIEW_BACKGROUND = False
|
||||
EPISODE_VIEW_BACKGROUND_TRANSLUCENT = False
|
||||
EPISODE_VIEW_LAYOUT = None
|
||||
EPISODE_VIEW_SORT = None
|
||||
EPISODE_VIEW_DISPLAY_PAUSED = False
|
||||
EPISODE_VIEW_POSTERS = True
|
||||
EPISODE_VIEW_MISSED_RANGE = None
|
||||
HISTORY_LAYOUT = None
|
||||
|
||||
FUZZY_DATING = False
|
||||
TRIM_ZERO = False
|
||||
DATE_PRESET = None
|
||||
|
@ -437,8 +452,6 @@ TIME_PRESET = None
|
|||
TIME_PRESET_W_SECONDS = None
|
||||
TIMEZONE_DISPLAY = None
|
||||
THEME_NAME = None
|
||||
POSTER_SORTBY = None
|
||||
POSTER_SORTDIR = None
|
||||
|
||||
USE_SUBTITLES = False
|
||||
SUBTITLES_LANGUAGES = []
|
||||
|
@ -462,6 +475,7 @@ REQUIRE_WORDS = ''
|
|||
CALENDAR_UNPROTECTED = False
|
||||
|
||||
TMDB_API_KEY = 'edc5f123313769de83a71e157758030b'
|
||||
FANART_API_KEY = '3728ca1a2a937ba0c93b6e63cc86cecb'
|
||||
|
||||
# to switch between staging and production TRAKT environment
|
||||
TRAKT_STAGING = False
|
||||
|
@ -518,13 +532,16 @@ def initialize(console_logging=True):
|
|||
# Views
|
||||
global GUI_NAME, HOME_LAYOUT, POSTER_SORTBY, POSTER_SORTDIR, DISPLAY_SHOW_SPECIALS, \
|
||||
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
|
||||
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, \
|
||||
VERSION_NOTIFY, AUTO_UPDATE, UPDATE_FREQUENCY, NOTIFY_ON_UPDATE
|
||||
# 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, \
|
||||
DATE_PRESET, TIME_PRESET, TIME_PRESET_W_SECONDS, TIMEZONE_DISPLAY, \
|
||||
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'):
|
||||
CheckSection(CFG, stanza)
|
||||
|
||||
update_config = False
|
||||
|
||||
# wanted 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')
|
||||
GUI_NAME = check_setting_str(CFG, 'GUI', 'gui_name', 'slick')
|
||||
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))
|
||||
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))
|
||||
|
@ -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')
|
||||
|
||||
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_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
|
||||
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))
|
||||
|
||||
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()
|
||||
|
||||
# start up all the threads
|
||||
|
@ -1199,8 +1239,8 @@ def initialize(console_logging=True):
|
|||
showUpdateScheduler = scheduler.Scheduler(
|
||||
show_updater.ShowUpdater(),
|
||||
cycleTime=datetime.timedelta(hours=1),
|
||||
threadName='SHOWUPDATER',
|
||||
start_time=datetime.time(hour=SHOW_UPDATE_HOUR),
|
||||
threadName='SHOWUPDATER',
|
||||
prevent_cycle_run=showQueueScheduler.action.isShowUpdateRunning) # 3AM
|
||||
|
||||
# searchers
|
||||
|
@ -1213,8 +1253,8 @@ def initialize(console_logging=True):
|
|||
recentSearchScheduler = scheduler.Scheduler(
|
||||
search_recent.RecentSearcher(),
|
||||
cycleTime=update_interval,
|
||||
threadName='RECENTSEARCHER',
|
||||
run_delay=update_now if RECENTSEARCH_STARTUP else datetime.timedelta(minutes=5),
|
||||
threadName='RECENTSEARCHER',
|
||||
prevent_cycle_run=searchQueueScheduler.action.is_recentsearch_in_progress)
|
||||
|
||||
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(
|
||||
search_backlog.BacklogSearcher(),
|
||||
cycleTime=datetime.timedelta(minutes=get_backlog_cycle_time()),
|
||||
threadName='BACKLOG',
|
||||
run_delay=datetime.timedelta(minutes=backlogdelay),
|
||||
threadName='BACKLOG',
|
||||
prevent_cycle_run=searchQueueScheduler.action.is_standard_backlog_in_progress)
|
||||
|
||||
propers_searcher = search_propers.ProperSearcher()
|
||||
|
@ -1251,9 +1291,9 @@ def initialize(console_logging=True):
|
|||
properFinderScheduler = scheduler.Scheduler(
|
||||
propers_searcher,
|
||||
cycleTime=update_interval,
|
||||
threadName='FINDPROPERS',
|
||||
start_time=run_at,
|
||||
run_delay=update_interval,
|
||||
start_time=run_at,
|
||||
threadName='FINDPROPERS',
|
||||
prevent_cycle_run=searchQueueScheduler.action.is_propersearch_in_progress)
|
||||
|
||||
# processors
|
||||
|
@ -1264,10 +1304,8 @@ def initialize(console_logging=True):
|
|||
silent=not PROCESS_AUTOMATICALLY)
|
||||
"""
|
||||
traktCheckerScheduler = scheduler.Scheduler(
|
||||
traktChecker.TraktChecker(),
|
||||
cycleTime=datetime.timedelta(hours=1),
|
||||
threadName='TRAKTCHECKER',
|
||||
silent=not USE_TRAKT)
|
||||
traktChecker.TraktChecker(), cycleTime=datetime.timedelta(hours=1),
|
||||
threadName='TRAKTCHECKER', silent=not USE_TRAKT)
|
||||
"""
|
||||
subtitlesFinderScheduler = scheduler.Scheduler(
|
||||
subtitles.SubtitlesFinder(),
|
||||
|
@ -1389,17 +1427,17 @@ def save_config():
|
|||
# For passwords you must include the word `password` in the item_name and
|
||||
# add `helpers.encrypt(ITEM_NAME, ENCRYPTION_VERSION)` in save_config()
|
||||
new_config['General'] = {}
|
||||
new_config['General']['config_version'] = CONFIG_VERSION
|
||||
new_config['General']['branch'] = BRANCH
|
||||
new_config['General']['git_remote'] = GIT_REMOTE
|
||||
new_config['General']['cur_commit_hash'] = CUR_COMMIT_HASH
|
||||
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']['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']['socket_timeout'] = SOCKET_TIMEOUT
|
||||
new_config['General']['web_port'] = WEB_PORT
|
||||
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_log'] = int(WEB_LOG)
|
||||
new_config['General']['web_root'] = WEB_ROOT
|
||||
|
@ -1753,6 +1791,9 @@ def save_config():
|
|||
new_config['GUI']['gui_name'] = GUI_NAME
|
||||
new_config['GUI']['theme_name'] = THEME_NAME
|
||||
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']['imdb_accounts'] = IMDB_ACCOUNTS
|
||||
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']['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']['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_sort'] = EPISODE_VIEW_SORT
|
||||
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']['poster_sortby'] = POSTER_SORTBY
|
||||
new_config['GUI']['poster_sortdir'] = POSTER_SORTDIR
|
||||
new_config['GUI']['show_tags'] = ','.join(SHOW_TAGS)
|
||||
new_config['GUI']['showlist_tagview'] = SHOWLIST_TAGVIEW
|
||||
new_config['GUI']['show_tag_default'] = SHOW_TAG_DEFAULT
|
||||
new_config['GUI']['history_layout'] = HISTORY_LAYOUT
|
||||
|
||||
new_config['Subtitles'] = {}
|
||||
new_config['Subtitles']['use_subtitles'] = int(USE_SUBTITLES)
|
||||
|
|
|
@ -120,6 +120,11 @@ class Quality:
|
|||
FAILED: 'Failed',
|
||||
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
|
||||
def _getStatusStrings(status):
|
||||
toReturn = {}
|
||||
|
|
|
@ -363,16 +363,14 @@ def make_dirs(path):
|
|||
parents
|
||||
"""
|
||||
|
||||
logger.log(u"Checking if the path " + path + " already exists", logger.DEBUG)
|
||||
|
||||
if not ek.ek(os.path.isdir, path):
|
||||
# Windows, create all missing folders
|
||||
if os.name == 'nt' or os.name == 'ce':
|
||||
if os.name in ('nt', 'ce'):
|
||||
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)
|
||||
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
|
||||
|
||||
# not Windows, create all missing folders and set permissions
|
||||
|
@ -389,14 +387,14 @@ def make_dirs(path):
|
|||
continue
|
||||
|
||||
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)
|
||||
# use normpath to remove end separator, otherwise checks permissions against itself
|
||||
chmodAsParent(ek.ek(os.path.normpath, sofar))
|
||||
# do the library update for synoindex
|
||||
notifiers.synoindex_notifier.addFolder(sofar)
|
||||
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 True
|
||||
|
@ -799,6 +797,18 @@ def md5_for_file(filename, block_size=2 ** 16):
|
|||
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():
|
||||
"""
|
||||
Simple function to get LAN localhost_ip
|
||||
|
@ -959,6 +969,7 @@ def validateShow(show, season=None, episode=None):
|
|||
|
||||
try:
|
||||
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':
|
||||
lINDEXER_API_PARMS['language'] = indexer_lang
|
||||
|
|
|
@ -16,17 +16,28 @@
|
|||
# You should have received a copy of the GNU General Public License
|
||||
# along with SickGear. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import datetime
|
||||
import fnmatch
|
||||
import glob
|
||||
import os.path
|
||||
import re
|
||||
import shutil
|
||||
import time
|
||||
|
||||
import sickbeard
|
||||
|
||||
from sickbeard import helpers, logger, exceptions
|
||||
from sickbeard import encodingKludge as ek
|
||||
from sickbeard import db
|
||||
|
||||
from sickbeard.metadata.generic import GenericMetadata
|
||||
|
||||
from lib.hachoir_parser import createParser
|
||||
from lib.hachoir_metadata import extractMetadata
|
||||
from lib.send2trash import send2trash
|
||||
try:
|
||||
import zlib
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
class ImageCache:
|
||||
|
@ -36,12 +47,21 @@ class ImageCache:
|
|||
def __del__(self):
|
||||
pass
|
||||
|
||||
def _cache_dir(self):
|
||||
@staticmethod
|
||||
def _cache_dir():
|
||||
"""
|
||||
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'))
|
||||
|
||||
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):
|
||||
"""
|
||||
Builds up the full path to the thumbnails image cache directory
|
||||
|
@ -53,94 +73,111 @@ class ImageCache:
|
|||
Builds up the path to a poster cache for a given Indexer ID
|
||||
|
||||
returns: a full path to the cached poster file for the given Indexer ID
|
||||
|
||||
|
||||
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(), poster_file_name)
|
||||
return ek.ek(os.path.join, self._cache_dir(), '%s.poster.jpg' % indexer_id)
|
||||
|
||||
def banner_path(self, indexer_id):
|
||||
"""
|
||||
Builds up the path to a banner cache for a given Indexer ID
|
||||
|
||||
returns: a full path to the cached banner file for the given Indexer ID
|
||||
|
||||
|
||||
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(), banner_file_name)
|
||||
return ek.ek(os.path.join, self._cache_dir(), '%s.banner.jpg' % indexer_id)
|
||||
|
||||
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):
|
||||
"""
|
||||
Builds up the path to a poster cache for a given Indexer ID
|
||||
|
||||
returns: a full path to the cached poster file for the given Indexer ID
|
||||
|
||||
|
||||
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(), posterthumb_file_name)
|
||||
return ek.ek(os.path.join, self._thumbnails_dir(), '%s.poster.jpg' % indexer_id)
|
||||
|
||||
def banner_thumb_path(self, indexer_id):
|
||||
"""
|
||||
Builds up the path to a poster cache for a given Indexer ID
|
||||
|
||||
returns: a full path to the cached poster file for the given Indexer ID
|
||||
|
||||
|
||||
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(), bannerthumb_file_name)
|
||||
return ek.ek(os.path.join, self._thumbnails_dir(), '%s.banner.jpg' % indexer_id)
|
||||
|
||||
@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):
|
||||
"""
|
||||
Returns true if a cached poster exists for the given Indexer ID
|
||||
"""
|
||||
poster_path = 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)
|
||||
return self.has_file(self.poster_path(indexer_id))
|
||||
|
||||
def has_banner(self, indexer_id):
|
||||
"""
|
||||
Returns true if a cached banner exists for the given Indexer ID
|
||||
"""
|
||||
banner_path = 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)
|
||||
return self.has_file(self.banner_path(indexer_id))
|
||||
|
||||
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):
|
||||
"""
|
||||
Returns true if a cached poster thumbnail exists for the given Indexer ID
|
||||
"""
|
||||
poster_thumb_path = 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)
|
||||
return self.has_file(self.poster_thumb_path(indexer_id))
|
||||
|
||||
def has_banner_thumbnail(self, indexer_id):
|
||||
"""
|
||||
Returns true if a cached banner exists for the given Indexer ID
|
||||
"""
|
||||
banner_thumb_path = 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)
|
||||
|
||||
return self.has_file(self.banner_thumb_path(indexer_id))
|
||||
|
||||
BANNER = 1
|
||||
POSTER = 2
|
||||
BANNER_THUMB = 3
|
||||
POSTER_THUMB = 4
|
||||
FANART = 5
|
||||
|
||||
def which_type(self, path):
|
||||
"""
|
||||
Analyzes the image provided and attempts to determine whether it is a poster or banner.
|
||||
|
||||
returns: BANNER, POSTER if it concluded one or the other, or None if the image was neither (or didn't exist)
|
||||
|
||||
Analyzes the image provided and attempts to determine whether it is a poster, banner or fanart.
|
||||
|
||||
returns: BANNER, POSTER, FANART or None if image type is not detected or doesn't exist
|
||||
|
||||
path: full path to the image
|
||||
"""
|
||||
|
||||
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
|
||||
|
||||
# use hachoir to parse the image for us
|
||||
|
@ -148,66 +185,105 @@ class ImageCache:
|
|||
img_metadata = extractMetadata(img_parser)
|
||||
|
||||
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
|
||||
|
||||
img_ratio = float(img_metadata.get('width')) / float(img_metadata.get('height'))
|
||||
|
||||
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)
|
||||
if 0.55 < img_ratio < 0.8:
|
||||
logger.log(msg_success % 'poster', logger.DEBUG)
|
||||
return self.POSTER
|
||||
|
||||
# most banners are around 5.4 width/height ratio (eg. 758/140)
|
||||
elif 5 < img_ratio < 6:
|
||||
logger.log(msg_success % 'banner', logger.DEBUG)
|
||||
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:
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
returns: bool representing success
|
||||
|
||||
image_path: path to the image we're caching
|
||||
img_type: BANNER or POSTER
|
||||
Takes the image provided and copies or moves it to the cache folder
|
||||
|
||||
returns: full path to cached file or None
|
||||
|
||||
image_path: path to the image to cache
|
||||
img_type: BANNER, POSTER, or FANART
|
||||
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
|
||||
fanart_subdir = []
|
||||
if img_type == self.POSTER:
|
||||
dest_path = self.poster_path(indexer_id)
|
||||
elif img_type == self.BANNER:
|
||||
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:
|
||||
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
|
||||
|
||||
# make sure the cache folder exists before we try copying to it
|
||||
if not ek.ek(os.path.isdir, self._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())
|
||||
for cache_dir in [self._cache_dir(), self._thumbnails_dir(), self._fanart_dir()] + fanart_subdir:
|
||||
helpers.make_dirs(cache_dir)
|
||||
|
||||
if not ek.ek(os.path.isdir, self._thumbnails_dir()):
|
||||
logger.log(u"Thumbnails cache directory doesn't exist, creating it at " + str(self._thumbnails_dir()))
|
||||
ek.ek(os.makedirs, self._thumbnails_dir())
|
||||
logger.log(u'%sing from %s to %s' % (('Copy', 'Mov')[move_file], image_path, dest_path))
|
||||
if move_file:
|
||||
helpers.moveFile(image_path, dest_path)
|
||||
else:
|
||||
helpers.copyFile(image_path, dest_path)
|
||||
|
||||
logger.log(u"Copying from " + image_path + " to " + dest_path)
|
||||
helpers.copyFile(image_path, dest_path)
|
||||
return ek.ek(os.path.isfile, dest_path) and dest_path or None
|
||||
|
||||
return True
|
||||
|
||||
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
|
||||
|
||||
|
||||
returns: bool representing success
|
||||
|
||||
|
||||
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
|
||||
|
@ -217,6 +293,9 @@ class ImageCache:
|
|||
elif img_type == self.BANNER:
|
||||
img_type_name = 'banner'
|
||||
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:
|
||||
img_type_name = 'poster_thumb'
|
||||
dest_path = self.poster_thumb_path(show_obj.indexerid)
|
||||
|
@ -224,70 +303,205 @@ class ImageCache:
|
|||
img_type_name = 'banner_thumb'
|
||||
dest_path = self.banner_thumb_path(show_obj.indexerid)
|
||||
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
|
||||
|
||||
# retrieve the image from indexer using the generic metadata class
|
||||
#TODO: refactor
|
||||
metadata_generator = GenericMetadata()
|
||||
img_data = metadata_generator._retrieve_show_image(img_type_name, show_obj)
|
||||
result = metadata_generator._write_image(img_data, dest_path)
|
||||
if img_type == self.FANART:
|
||||
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
|
||||
|
||||
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
|
||||
downloads them from indexer if they aren't in the show dir.
|
||||
|
||||
|
||||
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
|
||||
need_images = {self.POSTER: not self.has_poster(show_obj.indexerid),
|
||||
self.BANNER: not self.has_banner(show_obj.indexerid),
|
||||
self.POSTER_THUMB: not self.has_poster_thumbnail(show_obj.indexerid),
|
||||
self.BANNER_THUMB: not self.has_banner_thumbnail(show_obj.indexerid)}
|
||||
# check if any images are cached
|
||||
need_images = {self.POSTER: not self.has_poster(show_id),
|
||||
self.BANNER: not self.has_banner(show_id),
|
||||
self.FANART: 0 < sickbeard.FANART_LIMIT and (force or not self.has_fanart(show_id + '.001.*')),
|
||||
# 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 \
|
||||
need_images[self.BANNER_THUMB]:
|
||||
logger.log(u"No new cache images needed, not retrieving new ones")
|
||||
if not any(need_images.values()):
|
||||
logger.log(u'%s: No new cache images needed. Done.' % show_id)
|
||||
return
|
||||
|
||||
# check the show dir for poster or banner images and use them
|
||||
if need_images[self.POSTER] or need_images[self.BANNER]:
|
||||
try:
|
||||
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)
|
||||
void = False
|
||||
if not void and need_images[self.FANART]:
|
||||
action = ('delete', 'trash')[sickbeard.TRASH_REMOVE_SHOW]
|
||||
|
||||
if cur_file_type == None:
|
||||
logger.log(u"Unable to retrieve image type, not using the image from " + str(cur_file_name),
|
||||
logger.WARNING)
|
||||
cache_path = self.fanart_path(show_id).replace('%s.fanart.jpg' % show_id, '')
|
||||
# num_images = len(fnmatch.filter(os.listdir(cache_path), '*.jpg'))
|
||||
|
||||
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
|
||||
|
||||
logger.log(u"Checking if image " + cur_file_name + " (type " + str(
|
||||
cur_file_type) + " needs metadata: " + str(need_images[cur_file_type]), logger.DEBUG)
|
||||
logger.log(u'Checking if image %s (type %s needs metadata: %s)'
|
||||
% (cache_file_name, str(cur_file_type),
|
||||
('No', 'Yes')[True is need_images[cur_file_type]]), logger.DEBUG)
|
||||
|
||||
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:
|
||||
logger.log(u"Unable to search for images in show directory because it doesn't exist", logger.WARNING)
|
||||
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)
|
||||
|
||||
# download from indexer for missing ones
|
||||
for cur_image_type in [self.POSTER, self.BANNER, self.POSTER_THUMB, self.BANNER_THUMB]:
|
||||
logger.log(u"Seeing if we still need an image of type " + str(cur_image_type) + ": " + str(
|
||||
need_images[cur_image_type]), logger.DEBUG)
|
||||
if cur_image_type in need_images and need_images[cur_image_type]:
|
||||
self._cache_image_from_indexer(show_obj, cur_image_type)
|
||||
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)]))
|
||||
|
||||
logger.log(u"Done cache check")
|
||||
except exceptions.ShowDirNotFoundException:
|
||||
logger.log(u'Unable to search for images in show directory because it doesn\'t exist', logger.WARNING)
|
||||
|
||||
# download missing ones from indexer
|
||||
for image_type, name_type in [[self.POSTER, 'Poster'], [self.BANNER, 'Banner'], [self.FANART, 'Fanart'],
|
||||
[self.POSTER_THUMB, 'Poster Thumb'], [self.BANNER_THUMB, 'Banner Thumb']]:
|
||||
max_files = (500, sickbeard.FANART_LIMIT)[self.FANART == image_type]
|
||||
if not max_files or max_files < need_images[image_type]:
|
||||
continue
|
||||
|
||||
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')
|
||||
|
|
|
@ -37,6 +37,7 @@ try:
|
|||
except ImportError:
|
||||
pass
|
||||
|
||||
# ERROR = 40, WARNING = 30, INFO = 20, DEBUG = 10
|
||||
ERROR = logging.ERROR
|
||||
WARNING = logging.WARNING
|
||||
MESSAGE = logging.INFO
|
||||
|
@ -184,6 +185,37 @@ class SBRotatingLogHandler(object):
|
|||
else:
|
||||
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:
|
||||
def __init__(self, formatters, default_formatter):
|
||||
|
@ -263,7 +295,10 @@ class TimedCompressedRotatingFileHandler(TimedRotatingFileHandler):
|
|||
|
||||
if 0 < self.backupCount:
|
||||
# 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:
|
||||
all_names.sort()
|
||||
self.delete_logfile(all_names[0])
|
||||
|
|
|
@ -38,9 +38,13 @@ from sickbeard import logger
|
|||
from sickbeard import encodingKludge as ek
|
||||
from sickbeard.exceptions import ex
|
||||
from sickbeard.show_name_helpers import allPossibleShowNames
|
||||
from sickbeard.indexers import indexer_config
|
||||
|
||||
from six import iteritems
|
||||
|
||||
from lib.tmdb_api.tmdb_api import TMDB
|
||||
from lib.fanart.core import Request as fanartRequest
|
||||
import lib.fanart as fanart
|
||||
|
||||
|
||||
class GenericMetadata():
|
||||
|
@ -149,21 +153,21 @@ class GenericMetadata():
|
|||
|
||||
def _has_episode_thumb(self, 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:
|
||||
logger.log(u"Checking if " + location + " exists: " + str(result), logger.DEBUG)
|
||||
return result
|
||||
|
||||
def _has_season_poster(self, 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:
|
||||
logger.log(u"Checking if " + location + " exists: " + str(result), logger.DEBUG)
|
||||
return result
|
||||
|
||||
def _has_season_banner(self, 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:
|
||||
logger.log(u"Checking if " + location + " exists: " + str(result), logger.DEBUG)
|
||||
return result
|
||||
|
@ -742,30 +746,27 @@ class GenericMetadata():
|
|||
|
||||
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
|
||||
which: optional, a specific numbered poster to look for
|
||||
|
||||
Returns: the binary image data if available, or else None
|
||||
"""
|
||||
image_url = None
|
||||
indexer_lang = show_obj.lang
|
||||
|
||||
try:
|
||||
# There's gotta be a better way of doing this but we don't wanna
|
||||
# change the language value elsewhere
|
||||
lINDEXER_API_PARMS = sickbeard.indexerApi(show_obj.indexer).api_params.copy()
|
||||
|
||||
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
|
||||
|
||||
if show_obj.dvdorder != 0:
|
||||
lINDEXER_API_PARMS['dvdorder'] = True
|
||||
|
||||
t = sickbeard.indexerApi(show_obj.indexer).indexer(**lINDEXER_API_PARMS)
|
||||
indexer_show_obj = t[show_obj.indexerid]
|
||||
except (sickbeard.indexer_error, IOError) as e:
|
||||
|
@ -773,30 +774,59 @@ class GenericMetadata():
|
|||
show_obj.indexer).name + ", not downloading images: " + ex(e), logger.ERROR)
|
||||
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(
|
||||
show_obj.indexer).name + " object", logger.ERROR)
|
||||
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:
|
||||
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:
|
||||
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:
|
||||
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:
|
||||
image_url = indexer_show_obj[image_type]
|
||||
if image_url:
|
||||
image_urls.append(image_url)
|
||||
if 'poster' == image_type:
|
||||
init_url = image_url
|
||||
|
||||
# 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 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]))
|
||||
|
||||
if image_url:
|
||||
image_data = metadata_helpers.getShowImage(image_url, which)
|
||||
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 None
|
||||
|
@ -818,15 +848,12 @@ class GenericMetadata():
|
|||
# There's gotta be a better way of doing this but we don't wanna
|
||||
# change the language value elsewhere
|
||||
lINDEXER_API_PARMS = sickbeard.indexerApi(show_obj.indexer).api_params.copy()
|
||||
|
||||
lINDEXER_API_PARMS['banners'] = True
|
||||
lINDEXER_API_PARMS['dvdorder'] = 0 != show_obj.dvdorder
|
||||
|
||||
if indexer_lang and not indexer_lang == 'en':
|
||||
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)
|
||||
indexer_show_obj = t[show_obj.indexerid]
|
||||
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
|
||||
# change the language value elsewhere
|
||||
lINDEXER_API_PARMS = sickbeard.indexerApi(show_obj.indexer).api_params.copy()
|
||||
|
||||
lINDEXER_API_PARMS['banners'] = True
|
||||
lINDEXER_API_PARMS['dvdorder'] = 0 != show_obj.dvdorder
|
||||
|
||||
if indexer_lang and not indexer_lang == 'en':
|
||||
lINDEXER_API_PARMS['language'] = indexer_lang
|
||||
|
@ -950,10 +977,10 @@ class GenericMetadata():
|
|||
except:
|
||||
indexer = None
|
||||
|
||||
if showXML.findtext('tvdbid') != None:
|
||||
if None is not showXML.findtext('tvdbid'):
|
||||
indexer_id = int(showXML.findtext('tvdbid'))
|
||||
indexer = INDEXER_TVDB
|
||||
elif showXML.findtext('id') != None:
|
||||
elif None is not showXML.findtext('id'):
|
||||
indexer_id = int(showXML.findtext('id'))
|
||||
try:
|
||||
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)
|
||||
|
||||
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
|
||||
tmdb = TMDB(sickbeard.TMDB_API_KEY)
|
||||
config = tmdb.Configuration()
|
||||
|
@ -984,21 +1019,90 @@ class GenericMetadata():
|
|||
sizes = response['images']['poster_sizes']
|
||||
|
||||
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)
|
||||
|
||||
try:
|
||||
search = tmdb.Search()
|
||||
for show_name in set(allPossibleShowNames(show)):
|
||||
for result in search.collection({'query': show_name})['results'] + search.tv({'query': show_name})[
|
||||
'results']:
|
||||
if backdrop and result['backdrop_path']:
|
||||
return "{0}{1}{2}".format(base_url, max_size, result['backdrop_path'])
|
||||
elif poster and result['poster_path']:
|
||||
return "{0}{1}{2}".format(base_url, max_size, result['poster_path'])
|
||||
itemlist = []
|
||||
for (src, name) in [(indexer_config.INDEXER_TVDB, 'tvdb'), (indexer_config.INDEXER_IMDB, 'imdb'),
|
||||
(indexer_config.INDEXER_TVRAGE, 'tvrage')]:
|
||||
is_id = show.ids.get(src, {}).get('id', None)
|
||||
if not is_id:
|
||||
continue
|
||||
|
||||
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
|
||||
|
||||
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)
|
||||
|
|
|
@ -21,22 +21,18 @@ from sickbeard import logger
|
|||
|
||||
|
||||
def getShowImage(url, imgNum=None):
|
||||
image_data = None # @UnusedVariable
|
||||
|
||||
if url == None:
|
||||
if None is url:
|
||||
return None
|
||||
|
||||
# if they provided a fanart number try to use it instead
|
||||
if imgNum != None:
|
||||
tempURL = url.split('-')[0] + "-" + str(imgNum) + ".jpg"
|
||||
else:
|
||||
tempURL = url
|
||||
temp_url = url if None is imgNum else url.split('-')[0] + '-' + str(imgNum) + '.jpg'
|
||||
|
||||
logger.log(u"Fetching image from " + tempURL, logger.DEBUG)
|
||||
logger.log(u'Fetching image from ' + temp_url, logger.DEBUG)
|
||||
|
||||
image_data = helpers.getURL(tempURL)
|
||||
if image_data is None:
|
||||
logger.log(u"There was an error trying to retrieve the image, aborting", logger.ERROR)
|
||||
image_data = helpers.getURL(temp_url)
|
||||
if None is image_data:
|
||||
logger.log(u'There was an error trying to retrieve the image, aborting', logger.ERROR)
|
||||
return
|
||||
|
||||
return image_data
|
||||
|
|
|
@ -403,7 +403,7 @@ class GenericProvider:
|
|||
'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.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):
|
||||
return None
|
||||
|
|
|
@ -138,7 +138,7 @@ class ShowQueue(generic_queue.GenericQueue):
|
|||
return queueItemObj
|
||||
|
||||
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:
|
||||
raise exceptions.CantRefreshException('This show is already being refreshed, not refreshing again.')
|
||||
|
@ -149,7 +149,8 @@ class ShowQueue(generic_queue.GenericQueue):
|
|||
logger.DEBUG)
|
||||
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)
|
||||
|
||||
|
@ -487,7 +488,8 @@ class QueueItemAdd(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)
|
||||
|
||||
# do refreshes first because they're quick
|
||||
|
@ -496,6 +498,8 @@ class QueueItemRefresh(ShowQueueItem):
|
|||
# force refresh certain items
|
||||
self.force = force
|
||||
|
||||
self.force_image_cache = force_image_cache
|
||||
|
||||
self.kwargs = kwargs
|
||||
|
||||
def run(self):
|
||||
|
@ -507,7 +511,7 @@ class QueueItemRefresh(ShowQueueItem):
|
|||
self.show.writeMetadata()
|
||||
#if self.force:
|
||||
# self.show.updateMetadata()
|
||||
self.show.populateCache()
|
||||
self.show.populateCache(self.force_image_cache)
|
||||
|
||||
# Load XEM data to DB for show
|
||||
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:
|
||||
self.kwargs['priority'] = self.priority
|
||||
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):
|
||||
|
|
|
@ -17,18 +17,10 @@
|
|||
# along with SickGear. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import datetime
|
||||
import os
|
||||
|
||||
import sickbeard
|
||||
|
||||
from sickbeard import logger
|
||||
from sickbeard import exceptions
|
||||
from sickbeard import ui
|
||||
from sickbeard import logger, exceptions, ui, db, network_timezones, failed_history
|
||||
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:
|
||||
|
@ -109,7 +101,7 @@ class ShowUpdater:
|
|||
logger.log(
|
||||
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)
|
||||
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)
|
||||
|
||||
|
|
126
sickbeard/tv.py
|
@ -60,7 +60,7 @@ from sickbeard import encodingKludge as ek
|
|||
|
||||
from common import Quality, Overview, statusStrings
|
||||
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, \
|
||||
NAMING_LIMITED_EXTEND_E_PREFIXED
|
||||
|
||||
|
@ -503,12 +503,10 @@ class TVShow(object):
|
|||
t = sickbeard.indexerApi(self.indexer).indexer(**lINDEXER_API_PARMS)
|
||||
|
||||
cachedShow = t[self.indexerid]
|
||||
cachedSeasons = {}
|
||||
|
||||
if None is cachedShow:
|
||||
logger.log('No cache showdata to parse from %s' % sickbeard.indexerApi(self.indexer).name)
|
||||
return scannedEps
|
||||
|
||||
cachedSeasons = {}
|
||||
for curResult in sqlResults:
|
||||
|
||||
deleteEp = False
|
||||
|
@ -1072,19 +1070,26 @@ class TVShow(object):
|
|||
sickbeard.showList = [x for x in sickbeard.showList if int(x.indexerid) != self.indexerid]
|
||||
|
||||
# clear the cache
|
||||
image_cache_dir = ek.ek(os.path.join, sickbeard.CACHE_DIR, 'images')
|
||||
for path, dirs, files in ek.ek(os.walk, image_cache_dir):
|
||||
for filename in ek.ek(fnmatch.filter, files, '%s.*' % self.indexerid):
|
||||
cache_file = ek.ek(os.path.join, path, filename)
|
||||
logger.log('Attempt to %s cache file %s' % (action, cache_file))
|
||||
try:
|
||||
if sickbeard.TRASH_REMOVE_SHOW:
|
||||
ek.ek(send2trash, cache_file)
|
||||
else:
|
||||
ek.ek(os.remove, cache_file)
|
||||
ic = image_cache.ImageCache()
|
||||
for cache_obj in ek.ek(glob.glob, ic.poster_path(self.indexerid).replace('poster.jpg', '*')) \
|
||||
+ ek.ek(glob.glob, ic.poster_thumb_path(self.indexerid).replace('poster.jpg', '*')) \
|
||||
+ ek.ek(glob.glob, ic.fanart_path(self.indexerid).replace('%s.fanart.jpg' % self.indexerid, '')):
|
||||
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:
|
||||
if sickbeard.TRASH_REMOVE_SHOW:
|
||||
ek.ek(send2trash, cache_obj)
|
||||
elif cache_dir:
|
||||
ek.ek(shutil.rmtree, cache_obj)
|
||||
else:
|
||||
ek.ek(os.remove, cache_obj)
|
||||
|
||||
except OSError as e:
|
||||
logger.log('Unable to %s %s: %s / %s' % (action, cache_file, repr(e), str(e)), logger.WARNING)
|
||||
except OSError as e:
|
||||
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
|
||||
if full:
|
||||
|
@ -1092,7 +1097,7 @@ class TVShow(object):
|
|||
logger.log('Attempt to %s show folder %s' % (action, self._location))
|
||||
# check first the read-only attribute
|
||||
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
|
||||
logger.log('Attempting to make writeable the read only folder %s' % self._location, logger.DEBUG)
|
||||
try:
|
||||
|
@ -1114,11 +1119,11 @@ class TVShow(object):
|
|||
except OSError as e:
|
||||
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()
|
||||
|
||||
logger.log('Checking & filling cache for show %s' % self.name)
|
||||
cache_inst.fill_cache(self)
|
||||
cache_inst.fill_cache(self, force)
|
||||
|
||||
def refreshDir(self):
|
||||
|
||||
|
@ -1233,7 +1238,23 @@ class TVShow(object):
|
|||
try:
|
||||
helpers.moveFile(cache_file, new_cachefile)
|
||||
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)
|
||||
|
||||
|
@ -1294,27 +1315,21 @@ class TVShow(object):
|
|||
myDB.upsert('imdb_info', newValueDict, controlValueDict)
|
||||
|
||||
def __str__(self):
|
||||
toReturn = ''
|
||||
toReturn += 'indexerid: %s\n' % self.indexerid
|
||||
toReturn += 'indexer: %s\n' % self.indexer
|
||||
toReturn += 'name: %s\n' % self.name
|
||||
toReturn += 'location: %s\n' % self._location
|
||||
if self.network:
|
||||
toReturn += 'network: %s\n' % self.network
|
||||
if self.airs:
|
||||
toReturn += 'airs: %s\n' % self.airs
|
||||
if self.status:
|
||||
toReturn += 'status: %s\n' % self.status
|
||||
toReturn += 'startyear: %s\n' % self.startyear
|
||||
if self.genre:
|
||||
toReturn += 'genre: %s\n' % self.genre
|
||||
toReturn += 'classification: %s\n' % self.classification
|
||||
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
|
||||
return 'indexerid: %s\n' % self.indexerid \
|
||||
+ 'indexer: %s\n' % self.indexerid \
|
||||
+ 'name: %s\n' % self.name \
|
||||
+ 'location: %s\n' % self._location \
|
||||
+ ('', 'network: %s\n' % self.network)[self.network] \
|
||||
+ ('', 'airs: %s\n' % self.airs)[self.airs] \
|
||||
+ ('', 'status: %s\n' % self.status)[self.status] \
|
||||
+ 'startyear: %s\n' % self.startyear \
|
||||
+ ('', 'genre: %s\n' % self.genre)[self.genre] \
|
||||
+ 'classification: %s\n' % self.classification \
|
||||
+ 'runtime: %s\n' % self.runtime \
|
||||
+ 'quality: %s\n' % self.quality \
|
||||
+ 'scene: %s\n' % self.is_scene \
|
||||
+ 'sports: %s\n' % self.is_sports \
|
||||
+ 'anime: %s\n' % self.is_anime
|
||||
|
||||
def wantEpisode(self, season, episode, quality, manualSearch=False):
|
||||
|
||||
|
@ -1398,7 +1413,7 @@ class TVShow(object):
|
|||
return Overview.SKIPPED
|
||||
if status in (UNAIRED, UNKNOWN):
|
||||
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:
|
||||
return Overview.WANTED
|
||||
|
@ -1493,7 +1508,8 @@ class TVEpisode(object):
|
|||
release_group = property(lambda self: self._release_group, dirty_setter('_release_group'))
|
||||
|
||||
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
|
||||
dirty_setter('_location')(self, new_location)
|
||||
|
@ -1981,18 +1997,16 @@ class TVEpisode(object):
|
|||
|
||||
def __str__(self):
|
||||
|
||||
toReturn = ''
|
||||
toReturn += '%s - %sx%s - %s\n' % (self.show.name, self.season, self.episode, self.name)
|
||||
toReturn += 'location: %s\n' % self.location
|
||||
toReturn += 'description: %s\n' % self.description
|
||||
toReturn += 'subtitles: %s\n' % ','.join(self.subtitles)
|
||||
toReturn += 'subtitles_searchcount: %s\n' % self.subtitles_searchcount
|
||||
toReturn += 'subtitles_lastsearch: %s\n' % self.subtitles_lastsearch
|
||||
toReturn += 'airdate: %s (%s)\n' % (self.airdate.toordinal(), self.airdate)
|
||||
toReturn += 'hasnfo: %s\n' % self.hasnfo
|
||||
toReturn += 'hastbn: %s\n' % self.hastbn
|
||||
toReturn += 'status: %s\n' % self.status
|
||||
return toReturn
|
||||
return '%s - %sx%s - %s\n' % (self.show.name, self.season, self.episode, self.name) \
|
||||
+ 'location: %s\n' % self.location \
|
||||
+ 'description: %s\n' % self.description \
|
||||
+ 'subtitles: %s\n' % ','.join(self.subtitles) \
|
||||
+ 'subtitles_searchcount: %s\n' % self.subtitles_searchcount \
|
||||
+ 'subtitles_lastsearch: %s\n' % self.subtitles_lastsearch \
|
||||
+ 'airdate: %s (%s)\n' % (self.airdate.toordinal(), self.airdate) \
|
||||
+ 'hasnfo: %s\n' % self.hasnfo \
|
||||
+ 'hastbn: %s\n' % self.hastbn \
|
||||
+ 'status: %s\n' % self.status
|
||||
|
||||
def createMetaFiles(self):
|
||||
|
||||
|
@ -2067,7 +2081,7 @@ class TVEpisode(object):
|
|||
'(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.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.release_name, self.is_proper, self.show.indexerid, self.season, self.episode,
|
||||
self.absolute_number, self.version, self.release_group,
|
||||
|
|
|
@ -1235,50 +1235,65 @@ class CMD_Logs(ApiCall):
|
|||
ApiCall.__init__(self, handler, args, kwargs)
|
||||
|
||||
def run(self):
|
||||
""" view sickbeard's log """
|
||||
""" view sickgear's log """
|
||||
# 10 = Debug / 20 = Info / 30 = Warning / 40 = Error
|
||||
minLevel = logger.reverseNames[str(self.min_level).upper()]
|
||||
|
||||
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()
|
||||
min_level = logger.reverseNames[str(self.min_level).upper()]
|
||||
max_lines = 50
|
||||
|
||||
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
|
||||
lastLine = False
|
||||
numToShow = min(50, len(data))
|
||||
if os.path.isfile(logger.sb_log_instance.log_file_path):
|
||||
for x in logger.sb_log_instance.reverse_readline(logger.sb_log_instance.log_file_path):
|
||||
|
||||
for x in reversed(data):
|
||||
x = x.decode('utf-8')
|
||||
match = re.match(regex, x)
|
||||
|
||||
x = x.decode('utf-8')
|
||||
match = re.match(regex, x)
|
||||
if match:
|
||||
level = match.group(7)
|
||||
if level not in logger.reverseNames:
|
||||
normal_data = []
|
||||
continue
|
||||
|
||||
if match:
|
||||
level = match.group(7)
|
||||
if level not in logger.reverseNames:
|
||||
lastLine = False
|
||||
continue
|
||||
if logger.reverseNames[level] >= min_level:
|
||||
if truncate and not normal_data and truncate[0] == match.group(8) + match.group(9):
|
||||
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:
|
||||
normal_data = []
|
||||
continue
|
||||
|
||||
if logger.reverseNames[level] >= minLevel:
|
||||
lastLine = True
|
||||
finalData.append(x.rstrip("\n"))
|
||||
else:
|
||||
lastLine = False
|
||||
continue
|
||||
if not any(normal_data) and not any([x.strip()]):
|
||||
continue
|
||||
|
||||
elif lastLine:
|
||||
finalData.append("AA" + x)
|
||||
normal_data.append(re.sub(r'\r?\n', '<br />', x.replace('<', '<').replace('>', '>')))
|
||||
|
||||
numLines += 1
|
||||
num_lines += 1
|
||||
|
||||
if numLines >= numToShow:
|
||||
break
|
||||
if num_lines >= max_lines:
|
||||
break
|
||||
|
||||
return _responds(RESULT_SUCCESS, final_data)
|
||||
|
||||
return _responds(RESULT_SUCCESS, finalData)
|
||||
|
||||
class CMD_PostProcess(ApiCall):
|
||||
_help = {"desc": "Manual postprocess TV Download Dir",
|
||||
|
|
|
@ -22,6 +22,7 @@ from __future__ import with_statement
|
|||
import base64
|
||||
import datetime
|
||||
import dateutil.parser
|
||||
import glob
|
||||
import itertools
|
||||
import os
|
||||
import random
|
||||
|
@ -78,20 +79,18 @@ except ImportError:
|
|||
class PageTemplate(Template):
|
||||
def __init__(self, headers, *args, **kwargs):
|
||||
|
||||
self.sbHost = (re.match('(?msx)^' + (('[^:]+', '\[.*\]')['[' == headers['Host'][0]]), headers['Host']).group(0),
|
||||
headers.get('X-Forwarded-Host', ''))['X-Forwarded-Host' in headers]
|
||||
self.sbHost = headers.get('X-Forwarded-Host')
|
||||
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.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.sbHttpsEnabled = (sickbeard.ENABLE_HTTPS, 'https' == headers.get('X-Forwarded-Proto', ''))[
|
||||
'X-Forwarded-Proto' in headers]
|
||||
self.sbHttpsEnabled = 'https' == headers.get('X-Forwarded-Proto') or sickbeard.ENABLE_HTTPS
|
||||
self.sbHandleReverseProxy = sickbeard.HANDLE_REVERSE_PROXY
|
||||
self.sbThemeName = sickbeard.THEME_NAME
|
||||
|
||||
log_page_title = 'Logs & Errors'
|
||||
if len(classes.ErrorViewer.errors):
|
||||
log_page_title += ' (%s)' % len(classes.ErrorViewer.errors)
|
||||
self.logPageTitle = log_page_title
|
||||
self.log_num_errors = len(classes.ErrorViewer.errors)
|
||||
self.sbPID = str(sickbeard.PID)
|
||||
self.menu = [
|
||||
{'title': 'Home', 'key': 'home'},
|
||||
|
@ -99,7 +98,6 @@ class PageTemplate(Template):
|
|||
{'title': 'History', 'key': 'history'},
|
||||
{'title': 'Manage', 'key': 'manage'},
|
||||
{'title': 'Config', 'key': 'config'},
|
||||
{'title': log_page_title, 'key': 'errorlogs'},
|
||||
]
|
||||
|
||||
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):
|
||||
if sickbeard.WEB_USERNAME or sickbeard.WEB_PASSWORD:
|
||||
return self.get_secure_cookie('sickgear-session')
|
||||
else:
|
||||
return True
|
||||
return self.get_secure_cookie('sickgear-session-%s' % helpers.md5_for_text(sickbeard.WEB_PORT))
|
||||
return True
|
||||
|
||||
def showPoster(self, show=None, which=None, api=None):
|
||||
# Redirect initial poster/banner thumb to default images
|
||||
if which[0:6] == 'poster':
|
||||
if 'poster' == which[0:6]:
|
||||
default_image_name = 'poster.png'
|
||||
else:
|
||||
elif 'banner' == which[0:6]:
|
||||
default_image_name = 'banner.png'
|
||||
else:
|
||||
default_image_name = 'backart.png'
|
||||
|
||||
static_image_path = os.path.join('/images', default_image_name)
|
||||
if show and sickbeard.helpers.findCertainShow(sickbeard.showList, int(show)):
|
||||
cache_obj = image_cache.ImageCache()
|
||||
|
||||
image_file_name = None
|
||||
if which == 'poster':
|
||||
if 'poster' == which:
|
||||
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)
|
||||
if which == 'banner':
|
||||
elif 'banner' == which:
|
||||
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)
|
||||
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):
|
||||
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):
|
||||
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/'))
|
||||
else:
|
||||
next_arg = '&next=' + self.get_argument('next', '/home/')
|
||||
|
@ -197,7 +200,7 @@ class LoginHandler(BaseHandler):
|
|||
|
||||
class LogoutHandler(BaseHandler):
|
||||
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/')
|
||||
|
||||
|
||||
|
@ -251,10 +254,10 @@ class CalendarHandler(BaseHandler):
|
|||
ical += 'BEGIN:VEVENT%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)\
|
||||
+ 'SUMMARY:%s - %sx%s - %s%s' % (show['show_name'], str(episode['season']), str(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)\
|
||||
+ '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]))\
|
||||
+ u'SUMMARY:%s - %sx%s - %s%s' % (show['show_name'], episode['season'], episode['episode'], episode['name'], crlf)\
|
||||
+ u'UID:%s-%s-%s-E%sS%s%s' % (appname, datetime.date.today().isoformat(), show['show_name'].replace(' ', '-'), episode['episode'], episode['season'], crlf)\
|
||||
+ u'DESCRIPTION:%s on %s' % ((show['airs'] or '(Unknown airs)'), (show['network'] or 'Unknown network'))\
|
||||
+ ('' if not episode['description'] else u'%s%s' % (nl, episode['description'].splitlines()[0]))\
|
||||
+ '%sEND:VEVENT%s' % (crlf, crlf)
|
||||
|
||||
# Ending the iCal
|
||||
|
@ -389,21 +392,6 @@ class MainHandler(WebHandler):
|
|||
sickbeard.POSTER_SORTDIR = int(direction)
|
||||
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):
|
||||
if layout not in ('poster', 'banner', 'list', 'daybyday'):
|
||||
layout = 'banner'
|
||||
|
@ -425,6 +413,15 @@ class MainHandler(WebHandler):
|
|||
|
||||
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):
|
||||
if sort not in ('time', 'network', 'show'):
|
||||
sort = 'time'
|
||||
|
@ -497,18 +494,40 @@ class MainHandler(WebHandler):
|
|||
return (remove_article(value.lower()), value.lower())[sickbeard.SORT_ARTICLE]
|
||||
|
||||
# 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):
|
||||
sql_results[index]['localtime'] = sbdatetime.sbdatetime.convert_to_setting(network_timezones.parse_date_time(item['airdate'],
|
||||
item['airs'], item['network']))
|
||||
sql_results[index]['data_show_name'] = value_maybe_article(item['show_name'])
|
||||
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')
|
||||
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
|
||||
for img in ek.ek(glob.glob, cache_obj.fanart_path(show_id).replace('fanart.jpg', '*')) or []:
|
||||
match = re.search(r'\.(\d+(?:\.\w*)?\.(?:\w{5,8}))\.fanart\.', img, re.I)
|
||||
if not match:
|
||||
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
|
||||
if layout and layout in ('banner', 'daybyday', 'list', 'poster'):
|
||||
|
@ -516,8 +535,77 @@ class MainHandler(WebHandler):
|
|||
else:
|
||||
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()
|
||||
|
||||
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):
|
||||
t = PageTemplate(headers=self.request.headers, file='genericMessage.tmpl')
|
||||
t.submenu = self.HomeMenu()
|
||||
|
@ -529,7 +617,6 @@ class MainHandler(WebHandler):
|
|||
class Home(MainHandler):
|
||||
def HomeMenu(self):
|
||||
return [
|
||||
{'title': 'Add Shows', 'path': 'home/addShows/', },
|
||||
{'title': 'Manual Post-Processing', 'path': 'home/postprocess/'},
|
||||
{'title': 'Update Emby', 'path': 'home/updateEMBY/', 'requires': self.haveEMBY},
|
||||
{'title': 'Update Kodi', 'path': 'home/updateKODI/', 'requires': self.haveKODI},
|
||||
|
@ -606,6 +693,13 @@ class Home(MainHandler):
|
|||
|
||||
if 0 == len(t.showlists):
|
||||
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:
|
||||
t.network_images = {}
|
||||
|
@ -1143,6 +1237,44 @@ class Home(MainHandler):
|
|||
else:
|
||||
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):
|
||||
|
||||
if show is None:
|
||||
|
@ -1153,17 +1285,6 @@ class Home(MainHandler):
|
|||
if showObj is None:
|
||||
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.submenu = [{'title': 'Edit', 'path': 'home/editShow?show=%d' % showObj.indexerid}]
|
||||
|
||||
|
@ -1195,13 +1316,14 @@ class Home(MainHandler):
|
|||
elif sickbeard.showQueueScheduler.action.isInSubtitleQueue(showObj): # @UndefinedVariable
|
||||
show_message = 'This show is queued and awaiting subtitles download.'
|
||||
|
||||
t.force_update = 'home/updateShow?show=%d&force=1&web=1' % showObj.indexerid
|
||||
if not sickbeard.showQueueScheduler.action.isBeingAdded(showObj): # @UndefinedVariable
|
||||
if not sickbeard.showQueueScheduler.action.isBeingUpdated(showObj): # @UndefinedVariable
|
||||
t.submenu.append(
|
||||
{'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': 'Force Full Update', 'path': 'home/updateShow?show=%d&force=1&web=1' % showObj.indexerid})
|
||||
{'title': 'Force Full Update', 'path': t.force_update})
|
||||
t.submenu.append({'title': 'Update show in Emby',
|
||||
'path': 'home/updateEMBY%s' %
|
||||
(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})
|
||||
|
||||
t.show = showObj
|
||||
t.sqlResults = sqlResults
|
||||
t.seasonResults = seasonResults
|
||||
t.show_message = show_message
|
||||
|
||||
epCounts = {}
|
||||
epCats = {}
|
||||
epCounts[Overview.SKIPPED] = 0
|
||||
epCounts[Overview.WANTED] = 0
|
||||
epCounts[Overview.QUAL] = 0
|
||||
epCounts[Overview.GOOD] = 0
|
||||
epCounts[Overview.UNAIRED] = 0
|
||||
epCounts[Overview.SNATCHED] = 0
|
||||
epCounts['videos'] = {}
|
||||
epCounts['archived'] = {}
|
||||
epCounts['totals'] = {}
|
||||
highest_season = 0
|
||||
latest_season = 0
|
||||
ep_counts = {}
|
||||
ep_cats = {}
|
||||
ep_counts[Overview.SKIPPED] = 0
|
||||
ep_counts[Overview.WANTED] = 0
|
||||
ep_counts[Overview.QUAL] = 0
|
||||
ep_counts[Overview.GOOD] = 0
|
||||
ep_counts[Overview.UNAIRED] = 0
|
||||
ep_counts[Overview.SNATCHED] = 0
|
||||
ep_counts['videos'] = {}
|
||||
ep_counts['status'] = {}
|
||||
ep_counts['archived'] = {}
|
||||
ep_counts['totals'] = {}
|
||||
ep_counts['eps_most'] = 0
|
||||
ep_counts['eps_all'] = 0
|
||||
t.latest_season = 0
|
||||
t.has_special = False
|
||||
|
||||
for curResult in sqlResults:
|
||||
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
|
||||
my_db = db.DBConnection()
|
||||
|
||||
for row in my_db.select('SELECT season, count(*) AS cnt FROM tv_episodes WHERE showid = ?'
|
||||
+ ' GROUP BY season', [showObj.indexerid]):
|
||||
ep_counts['totals'][row['season']] = row['cnt']
|
||||
|
||||
if None is not ep_counts['totals'].get(0, None):
|
||||
t.has_special = True
|
||||
if not sickbeard.DISPLAY_SHOW_SPECIALS:
|
||||
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:
|
||||
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']
|
||||
ep_counts['status'].setdefault(row['season'], {status_overview: row['cnt']})
|
||||
|
||||
if 0 < len(epCounts['totals']):
|
||||
latest_season = int(sorted(epCounts['totals'])[-1::][0])
|
||||
|
||||
display_seasons = []
|
||||
if 1 < highest_season:
|
||||
display_seasons += [1]
|
||||
display_seasons += [highest_season]
|
||||
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()
|
||||
|
||||
tvshows = []
|
||||
tvshow_names = []
|
||||
cur_sel = None
|
||||
|
@ -1291,19 +1438,42 @@ class Home(MainHandler):
|
|||
if showObj.is_anime:
|
||||
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)
|
||||
|
||||
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)
|
||||
indexer = int(showObj.indexer)
|
||||
t.all_scene_exceptions = showObj.exceptions
|
||||
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.xem_numbering = get_xem_numbering_for_show(indexerid, indexer)
|
||||
t.xem_absolute_numbering = get_xem_absolute_numbering_for_show(indexerid, indexer)
|
||||
|
||||
return t.respond()
|
||||
|
@ -1320,6 +1490,28 @@ class Home(MainHandler):
|
|||
results = filter(lambda x: x.tag == tag, sickbeard.showList)
|
||||
if results:
|
||||
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:
|
||||
shows = []
|
||||
anime = []
|
||||
|
@ -1342,7 +1534,7 @@ class Home(MainHandler):
|
|||
result = myDB.select(
|
||||
'SELECT description FROM tv_episodes WHERE showid = ? AND season = ? AND 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):
|
||||
exceptionsList = sickbeard.scene_exceptions.get_all_scene_exceptions(show)
|
||||
|
@ -1351,10 +1543,8 @@ class Home(MainHandler):
|
|||
|
||||
out = []
|
||||
for season, names in iter(sorted(iteritems(exceptionsList))):
|
||||
if season == -1:
|
||||
season = '*'
|
||||
out.append('S' + str(season) + ': ' + ', '.join(names))
|
||||
return '<br/>'.join(out)
|
||||
out.append('S%s: %s' % ((season, '*')[-1 == season], ',<br />\n'.join(names)))
|
||||
return '---------<br />\n'.join(out)
|
||||
|
||||
def switchIndexer(self, indexerid, indexer, mindexerid, mindexer, set_pause=False, mark_wanted=False):
|
||||
indexer = helpers.tryInt(indexer)
|
||||
|
@ -1473,11 +1663,38 @@ class Home(MainHandler):
|
|||
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()})
|
||||
|
||||
@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=[],
|
||||
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,
|
||||
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:
|
||||
errString = 'Invalid show ID: ' + str(show)
|
||||
|
@ -1528,6 +1745,10 @@ class Home(MainHandler):
|
|||
t.show = showObj
|
||||
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()
|
||||
|
||||
flatten_folders = config.checkbox_to_value(flatten_folders)
|
||||
|
@ -1540,6 +1761,10 @@ class Home(MainHandler):
|
|||
anime = config.checkbox_to_value(anime)
|
||||
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']:
|
||||
indexer_lang = indexerLang
|
||||
else:
|
||||
|
@ -1955,14 +2180,17 @@ class Home(MainHandler):
|
|||
if cur_ep_obj.location:
|
||||
if cur_ep_obj.relatedEps:
|
||||
# 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]:
|
||||
if cur_related_ep in ep_obj_rename_list:
|
||||
have_already = True
|
||||
break
|
||||
if not have_already:
|
||||
ep_obj_rename_list.append(cur_ep_obj)
|
||||
ep_status, ep_qual = Quality.splitCompositeStatus(cur_related_ep.status)
|
||||
if not ep_qual:
|
||||
continue
|
||||
ep_obj_rename_list.append(cur_ep_obj)
|
||||
else:
|
||||
ep_status, ep_qual = Quality.splitCompositeStatus(cur_ep_obj.status)
|
||||
if not ep_qual:
|
||||
continue
|
||||
ep_obj_rename_list.append(cur_ep_obj)
|
||||
|
||||
if ep_obj_rename_list:
|
||||
|
@ -1974,6 +2202,9 @@ class Home(MainHandler):
|
|||
t.ep_obj_list = ep_obj_rename_list
|
||||
t.show = showObj
|
||||
|
||||
# noinspection PyTypeChecker
|
||||
self.fanart_tmpl(t)
|
||||
|
||||
return t.respond()
|
||||
|
||||
def doRename(self, show=None, eps=None):
|
||||
|
@ -3214,7 +3445,7 @@ class NewHomeAddShows(Home):
|
|||
|
||||
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
|
||||
"""
|
||||
|
@ -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.ERROR)
|
||||
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_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
|
||||
if ek.ek(os.path.isdir, show_dir) and not fullShowPath:
|
||||
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
|
||||
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,
|
||||
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,
|
||||
show_tags=None, showlist_tagview=None):
|
||||
fanart_limit=None, show_tags=None, showlist_tagview=None):
|
||||
|
||||
results = []
|
||||
|
||||
# Misc
|
||||
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.SHOW_UPDATE_HOUR = config.minimax(show_update_hour, 3, 0, 23)
|
||||
sickbeard.TRASH_REMOVE_SHOW = config.checkbox_to_value(trash_remove_show)
|
||||
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)
|
||||
sickbeard.LAUNCH_BROWSER = config.checkbox_to_value(launch_browser)
|
||||
sickbeard.HOME_SEARCH_FOCUS = config.checkbox_to_value(home_search_focus)
|
||||
sickbeard.USE_IMDB_INFO = config.checkbox_to_value(use_imdb_info)
|
||||
sickbeard.SORT_ARTICLE = config.checkbox_to_value(sort_article)
|
||||
sickbeard.CPU_PRESET = cpu_preset
|
||||
sickbeard.FILE_LOGGING_PRESET = file_logging_preset
|
||||
sickbeard.NOTIFY_ON_UPDATE = config.checkbox_to_value(notify_on_update)
|
||||
|
||||
# Interface
|
||||
sickbeard.THEME_NAME = theme_name
|
||||
sickbeard.DEFAULT_HOME = default_home
|
||||
sickbeard.FANART_LIMIT = config.minimax(fanart_limit, 3, 0, 500)
|
||||
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.
|
||||
# Deduped list order preservation is key to feature function.
|
||||
myDB = db.DBConnection()
|
||||
sql_results = myDB.select('SELECT DISTINCT tag FROM tv_shows')
|
||||
# 'Show List' is the must have default fallback. Tags in use that are removed from config ui are restored,
|
||||
# not deleted. Deduped list order preservation is key to feature function.
|
||||
my_db = db.DBConnection()
|
||||
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()]
|
||||
orphans = [item for item in [v['tag'] for v in sql_results or []] if item not in new_names]
|
||||
cleanser = []
|
||||
|
@ -4419,75 +4657,60 @@ class ConfigGeneral(Config):
|
|||
sickbeard.SHOW_TAGS = [dedupe.setdefault(item, item) for item in (cleanser + new_names + [u'Show List'])
|
||||
if item not in dedupe]
|
||||
|
||||
logger.log_set_level()
|
||||
|
||||
sickbeard.ANON_REDIRECT = anon_redirect
|
||||
sickbeard.PROXY_SETTING = proxy_setting
|
||||
sickbeard.PROXY_INDEXERS = config.checkbox_to_value(proxy_indexers)
|
||||
sickbeard.GIT_PATH = git_path
|
||||
sickbeard.GIT_REMOTE = git_remote
|
||||
sickbeard.CALENDAR_UNPROTECTED = config.checkbox_to_value(calendar_unprotected)
|
||||
# sickbeard.LOG_DIR is set in config.change_LOG_DIR()
|
||||
|
||||
sickbeard.WEB_PORT = config.to_int(web_port)
|
||||
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)
|
||||
sickbeard.HOME_SEARCH_FOCUS = config.checkbox_to_value(home_search_focus)
|
||||
sickbeard.USE_IMDB_INFO = config.checkbox_to_value(use_imdb_info)
|
||||
sickbeard.SORT_ARTICLE = config.checkbox_to_value(sort_article)
|
||||
sickbeard.FUZZY_DATING = config.checkbox_to_value(fuzzy_dating)
|
||||
sickbeard.TRIM_ZERO = config.checkbox_to_value(trim_zero)
|
||||
if date_preset:
|
||||
sickbeard.DATE_PRESET = date_preset
|
||||
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
|
||||
|
||||
# Web interface
|
||||
reload_page = False
|
||||
|
||||
if sickbeard.WEB_USERNAME != web_username:
|
||||
sickbeard.WEB_USERNAME = web_username
|
||||
reload_page = True
|
||||
|
||||
if set('*') != set(web_password):
|
||||
sickbeard.WEB_PASSWORD = web_password
|
||||
reload_page = True
|
||||
|
||||
sickbeard.FUZZY_DATING = config.checkbox_to_value(fuzzy_dating)
|
||||
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.CALENDAR_UNPROTECTED = config.checkbox_to_value(calendar_unprotected)
|
||||
sickbeard.USE_API = config.checkbox_to_value(use_api)
|
||||
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)
|
||||
|
||||
if not config.change_HTTPS_CERT(https_cert):
|
||||
results += [
|
||||
'Unable to create directory ' + os.path.normpath(https_cert) + ', https cert directory not changed.']
|
||||
|
||||
if not config.change_HTTPS_KEY(https_key):
|
||||
results += [
|
||||
'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.THEME_NAME = theme_name
|
||||
sickbeard.DEFAULT_HOME = default_home
|
||||
# Advanced
|
||||
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()
|
||||
|
||||
if len(results) > 0:
|
||||
if 0 < len(results):
|
||||
for v in results:
|
||||
logger.log(v, logger.ERROR)
|
||||
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))
|
||||
|
||||
if reload_page:
|
||||
self.clear_cookie('sickgear-session')
|
||||
self.clear_cookie('sickgear-session-%s' % helpers.md5_for_text(sickbeard.WEB_PORT))
|
||||
self.write('reload')
|
||||
|
||||
@staticmethod
|
||||
|
@ -4994,6 +5217,7 @@ class ConfigProviders(Config):
|
|||
|
||||
cur_name, cur_url, cur_key, cur_cat = curNewznabProviderStr.split('|')
|
||||
cur_url = config.clean_url(cur_url)
|
||||
cur_key = cur_key.strip()
|
||||
|
||||
if starify(cur_key, True):
|
||||
cur_key = ''
|
||||
|
@ -5552,8 +5776,10 @@ class UI(MainHandler):
|
|||
class ErrorLogs(MainHandler):
|
||||
@staticmethod
|
||||
def ErrorLogsMenu():
|
||||
return [{'title': 'Download Log', 'path': 'errorlogs/downloadlog/'},
|
||||
{'title': 'Clear Errors', 'path': 'errorlogs/clearerrors/'},]
|
||||
if len(classes.ErrorViewer.errors):
|
||||
return [{'title': 'Download Log', 'path': 'errorlogs/downloadlog/'},
|
||||
{'title': 'Clear Errors', 'path': 'errorlogs/clearerrors/'},]
|
||||
return [{'title': 'Download Log', 'path': 'errorlogs/downloadlog/'},]
|
||||
|
||||
def index(self, *args, **kwargs):
|
||||
|
||||
|
@ -5583,56 +5809,73 @@ class ErrorLogs(MainHandler):
|
|||
except (StandardError, Exception):
|
||||
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.submenu = self.ErrorLogsMenu
|
||||
|
||||
minLevel = int(minLevel)
|
||||
|
||||
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()
|
||||
min_level = int(min_level)
|
||||
|
||||
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
|
||||
lastLine = False
|
||||
numToShow = min(maxLines, len(data))
|
||||
if os.path.isfile(logger.sb_log_instance.log_file_path):
|
||||
for x in logger.sb_log_instance.reverse_readline(logger.sb_log_instance.log_file_path):
|
||||
|
||||
for x in reversed(data):
|
||||
x = x.decode('utf-8', 'replace')
|
||||
match = re.match(regex, x)
|
||||
|
||||
x = x.decode('utf-8', 'replace')
|
||||
match = re.match(regex, x)
|
||||
if match:
|
||||
level = match.group(7)
|
||||
if level not in logger.reverseNames:
|
||||
normal_data = []
|
||||
continue
|
||||
|
||||
if match:
|
||||
level = match.group(7)
|
||||
if level not in logger.reverseNames:
|
||||
lastLine = False
|
||||
continue
|
||||
if logger.reverseNames[level] >= min_level:
|
||||
if truncate and not normal_data and truncate[0] == match.group(8) + match.group(9):
|
||||
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:
|
||||
normal_data = []
|
||||
continue
|
||||
|
||||
if logger.reverseNames[level] >= minLevel:
|
||||
lastLine = True
|
||||
finalData.append(x)
|
||||
else:
|
||||
lastLine = False
|
||||
continue
|
||||
if not any(normal_data) and not any([x.strip()]):
|
||||
continue
|
||||
|
||||
elif lastLine:
|
||||
finalData.append('AA' + x)
|
||||
normal_data.append(re.sub(r'\r?\n', '<br />', x.replace('<', '<').replace('>', '>')))
|
||||
|
||||
numLines += 1
|
||||
num_lines += 1
|
||||
|
||||
if numLines >= numToShow:
|
||||
break
|
||||
if num_lines >= max_lines:
|
||||
break
|
||||
|
||||
result = ''.join(finalData)
|
||||
result = ''.join(final_data)
|
||||
|
||||
t.logLines = result
|
||||
t.minLevel = minLevel
|
||||
t.min_level = min_level
|
||||
|
||||
return t.respond()
|
||||
|
||||
|
|