From bc0b8c0ae48bbf87bc5e6f7385a084648e55bb5b Mon Sep 17 00:00:00 2001 From: Supremicus Date: Mon, 15 Dec 2014 10:02:19 +1000 Subject: [PATCH 01/21] Add and change network logos. --- CHANGES.md | 8 ++++++++ gui/slick/images/network/bbc canada.png | Bin 0 -> 3783 bytes gui/slick/images/network/crackle.png | Bin 0 -> 2715 bytes gui/slick/images/network/el rey network.png | Bin 0 -> 2649 bytes gui/slick/images/network/sky atlantic.png | Bin 0 -> 2820 bytes gui/slick/images/network/watch.png | Bin 0 -> 3778 bytes gui/slick/images/network/yahoo! screen.png | Bin 3716 -> 5883 bytes 7 files changed, 8 insertions(+) create mode 100644 gui/slick/images/network/bbc canada.png create mode 100644 gui/slick/images/network/crackle.png create mode 100644 gui/slick/images/network/el rey network.png create mode 100644 gui/slick/images/network/sky atlantic.png create mode 100644 gui/slick/images/network/watch.png diff --git a/CHANGES.md b/CHANGES.md index ccb0721d..b4ad40b7 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,11 @@ +### 0.x.x (2014-12-xx xx:xx:xx UTC) + +* Add network logo's for BBC Canada, Crackle, El Rey Network, SKY Atlantic, and Watch +* Change Yahoo! screen network logo + +[develop changelog] + + ### 0.5.0 (2014-12-14 13:55:00 UTC) * Fix searches freezing due to unescaped ignored or required words diff --git a/gui/slick/images/network/bbc canada.png b/gui/slick/images/network/bbc canada.png new file mode 100644 index 0000000000000000000000000000000000000000..598d0ea6c2d9227eac90e7dacbcbf2d74ceba598 GIT binary patch literal 3783 zcmaJ^c|25Y8y>P`jU-!`M)qZ9>@&!|B}^h~)|nX0Viq&V60+}-B$1IViG;FC)?_I} zBq6eIt&+a+esAyh{qgmk-|w7fyRPfL@8`bHd44AzVP(q2F3b)90JzM}jBMzw9{mO$ zW}!a|^TML(jS$J$fpi{siA3=rpaA+voF@usj`8qD*`Pd-K>@ueZ2;g95N+!~a=>ixO$pc8m_+yE1st)KcT{yjeFbxI)|ALVGbU^=h%E1x= zG{g~5Ks6WG&B@|$`B|73{eI{l@*~Ha1~`Z1Ooi~0@1AzkeA># zMkasTqK|YyJ|q$z4hB;w6eWs^5{}>vhQeU50}W+mMLI%}7=$HxP!+L6iQfuFD54hu zjVGaTSm1%8hbN9q(gD#u{dWi${6Df-;@{gu-!L%M0}qBOK@LLt4YaiU|4#M38>uahQ!=O-ORr)~9Koer3 zZ(yXUW?-oHn`?ygB4bck(r+&EKU{-9at{gtgQr_ILJ`n`D5MDihXMW-FdY47Uo`)y z_cs^$XJ24{{Dnl(q==fRsHm#?`s|l! zcR16|lxDsh((m4m;@IVZkN!yhKq22B8*zT%+I-YBRg9l*3A)b2wY9m)bNck@!hpH1 zjhlvYD#^tq*7*s0dzZ_caY-d5B_AhhN*ovECzt!zFFiY3T1+SSQS`L^lgk3LSE^EO!-&P4I6oEx z>-qV4m$ujB5!(DwB;8wzgRSi~pRtM@JNQz66zh=$3DcCg#ld_&c_%$>m}oSSj2$lQ zRDCnq9P+iE_Wt6X)zwvnR#q04{c6Kl?%A!mZe_Xk>1L7qtgKq!fm<*qs?#m8l$4ay zcpwRCbI#u-P6X~3bOB17RBatZSCz7i!F1VYQ09x zO?mLORYiO?H8pFMZmrlRT<^>!_pNtYFqq;ks8`I#$@&eEuOXk8B~4Pr6bm!}gCnV| zV~jmNe^dZx*^@O&Ml#HXz!~2yM(;b<*HO2?ZY|fi+o*AeL;bdPhim=pcOrZk3Loe@ zau^65<>%+0?axt}`h1ns&UxqtT&UqN#c=>T-6T7ZubV%=uu!M1sygDSLs_4Ce`&rW z=I+lQU+bGe4x4A&mtK|Vc9uKjri@#9bL?Hgza6 zeG#53dpPY!D;$U)ukw%;zEf6Faje8D@2HTF&X>Nv}$q_&GMGN#G2@&+zH0H>Ro=#3TIRekM!7i*t zun_2ZzD%3vb@{sfHUzGrK{03z`#J4=@$tzUUnOjdKbSo?X41+vyDmA}b!|vy9%l%g zb&MPydJ4!n16Br4!!qZuXTf)i7qO$cxOGcZaK3kBG(5*SCT* z8XH3Z>66F9tfL$ru*IEa$Pmf^DQj4?XMIdPT0g%$dM|!u?7oGds!y6i=ri7BNkoPy z$Y8rWMO5phoS2@(lMX@SM#{!MOTGlZ`$gL8>doX#X=|zKYPmgqM9)CWn};Zi8=n4Z zO!^NE5VJT#0|SMz?xxiEcwVi*RWkrW92PKZbQ~#&{fr1sbZ~t?WIV300*cTY*k*k6 zwx~6QnKdBWf%19pO-B1p$4q-vsGgffPBanXr$%;~Ls&|i4{g5hF!iW64R{^2Q1DaH zx$cCXvk?CVF``-aBZO1h@+NWxJ!C~J4C7G&j{*Bxpnb4Ed>;XXS3w zo$2txPs1HSX=PFyh+VyXmhVZAeFIq4xpOM0Y!eQ(v9J?y^H1^`3$(}C$W5wBN>&lgTS#?XC^UdS z>(r@J&mvFm=aGYV7G7v?Ds(mDYR&QCtbMPodw_>{hlCu)n`=UeqfqD|@S6 zem!dj&QNuoiw}pxd41c-)M3A-7o=>9E)mVbUGa6A}~@q&)wwlgYlosBP?ZPt`aforD!VK+CoWSn1h7SwIFOgvhLm-85{3q!Sy-N*|HO4d zivEsD#eFjIv$pCJLUP#F+9y_;LC$m&B9ps_x^ru9|wT|Kn z4V_;;x_erbb%pVT$YECgwi_vDYN@p9`3d@ma&kgjGV{<1yKVSG!QPQ%5sk`WHkTyO zh5Q`3F0JPFk*7YY0*raN35kgx;(4u{@7GSegYGB$WXX2E9b27y`n<32%g||MgHa*& z(m{qVaK^2c+t=KFd|8VUtgIMxaA4ZWL0)|l!+S4WuxysuFyryPsjCqYfR114JIQkD zxv;^~_hmeA8XHzrEAW~kCMk8=E0fj*7wYW!fhcCml^Wvj^YPq`RN6^@yj!|?F4`5? z9Mj3Ob5KM`@~X+)ydZ0=Xa}w1g(fhPmn8)#qCVG^oEaUV2LD7>1>FTejF<1iOp-~V#g4ehtIyQC($mi(l8s@Sh zO`xT#?`%zE>;b;;H-eLv9Y`(qxt2oBq51n zt2{ZwjIQ-}t!^>A?HPUPZsDkCcMlW~7R4^@KAmm^J;9(Sj4rdY(u~eaefgMKB7uBU z%Od0Mes%K$(&@I#t*D~vgtn#qiti*jw&QtSwn(F*yLaQ)ChMj3Q?E!Hyt$%QVblNU zEOdPItYL8+TrH(Em5p!~m;iF?c=C$VPB=mPW-OZxn@zu6k(qTM-n~@p1((@XJJp1z zzqqK|k$kJ0E_v%ud_GQ_Eh03J1oriuA`e#I8iO>K#wNc0%Av_x`71FoYA@6OoVR%6 rxVPol7g>@dAKxaYv*VFp@@;^$u146^2Z3)6el5+7t&A!S+#~-5|KhLy literal 0 HcmV?d00001 diff --git a/gui/slick/images/network/crackle.png b/gui/slick/images/network/crackle.png new file mode 100644 index 0000000000000000000000000000000000000000..77d546822d7592fdfe1da9bae17e223ea6172770 GIT binary patch literal 2715 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 literal 0 HcmV?d00001 diff --git a/gui/slick/images/network/sky atlantic.png b/gui/slick/images/network/sky atlantic.png new file mode 100644 index 0000000000000000000000000000000000000000..46dc63845e1cd34456465c5ee9c86a0042f9391d GIT binary patch literal 2820 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 KeTgmgZ?&C?s*;xn+$O-@e0AVXj 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 literal 0 HcmV?d00001 diff --git a/gui/slick/images/network/yahoo! screen.png b/gui/slick/images/network/yahoo! screen.png index e9efa1b67cad4d95336b9c57e528dd21289321e6..7e16628bb681657f45e2fb7c575b6c36e89bb781 100644 GIT binary patch literal 5883 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 literal 3716 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 From 28cea6fb547309ff1b0c47e73fb458b16303bb63 Mon Sep 17 00:00:00 2001 From: Supremicus Date: Thu, 18 Dec 2014 13:04:27 +1000 Subject: [PATCH 02/21] Add/Update/Remove Network logo's * Change added and updated Discovery Network's channel logo's * Remove unrequired duplicate network logo's --- CHANGES.md | 2 ++ gui/slick/images/network/aande.png | Bin 4864 -> 0 bytes gui/slick/images/network/ahc.png | Bin 0 -> 2964 bytes gui/slick/images/network/animalplanet.png | Bin 5040 -> 0 bytes .../images/network/{bio..png => bio.png} | Bin gui/slick/images/network/cartoonnetwork.png | Bin 5832 -> 0 bytes gui/slick/images/network/comedycentral.png | Bin 4970 -> 0 bytes .../images/network/destination america.png | Bin 0 -> 4641 bytes .../images/network/discovery channel.png | Bin 5285 -> 3740 bytes gui/slick/images/network/discovery family.png | Bin 0 -> 4613 bytes gui/slick/images/network/discovery.png | Bin 5285 -> 3740 bytes gui/slick/images/network/discoverychannel.png | Bin 5285 -> 0 bytes gui/slick/images/network/disneychannel.png | Bin 7823 -> 0 bytes gui/slick/images/network/fxnetworks.png | Bin 3904 -> 0 bytes gui/slick/images/network/g4_2.png | Bin 3960 -> 0 bytes .../network/investigation discovery.png | Bin 0 -> 2868 bytes .../images/network/the discovery channel.png | Bin 0 -> 3740 bytes gui/slick/images/network/the hub.png | Bin 0 -> 3102 bytes gui/slick/images/network/the-cw.png | Bin 3576 -> 0 bytes gui/slick/images/network/thecw.png | Bin 3576 -> 0 bytes gui/slick/images/network/thewb.png | Bin 4733 -> 0 bytes gui/slick/images/network/tlc.png | Bin 0 -> 2594 bytes gui/slick/images/network/usa-network.png | Bin 3830 -> 0 bytes gui/slick/images/network/usanetwork.png | Bin 3830 -> 0 bytes gui/slick/images/network/velocity.png | Bin 0 -> 3200 bytes 25 files changed, 2 insertions(+) delete mode 100644 gui/slick/images/network/aande.png create mode 100644 gui/slick/images/network/ahc.png delete mode 100644 gui/slick/images/network/animalplanet.png rename gui/slick/images/network/{bio..png => bio.png} (100%) delete mode 100644 gui/slick/images/network/cartoonnetwork.png delete mode 100644 gui/slick/images/network/comedycentral.png create mode 100644 gui/slick/images/network/destination america.png create mode 100644 gui/slick/images/network/discovery family.png delete mode 100644 gui/slick/images/network/discoverychannel.png delete mode 100644 gui/slick/images/network/disneychannel.png delete mode 100644 gui/slick/images/network/fxnetworks.png delete mode 100644 gui/slick/images/network/g4_2.png create mode 100644 gui/slick/images/network/investigation discovery.png create mode 100644 gui/slick/images/network/the discovery channel.png create mode 100644 gui/slick/images/network/the hub.png delete mode 100644 gui/slick/images/network/the-cw.png delete mode 100644 gui/slick/images/network/thecw.png delete mode 100644 gui/slick/images/network/thewb.png create mode 100644 gui/slick/images/network/tlc.png delete mode 100644 gui/slick/images/network/usa-network.png delete mode 100644 gui/slick/images/network/usanetwork.png create mode 100644 gui/slick/images/network/velocity.png diff --git a/CHANGES.md b/CHANGES.md index a5fc0f71..c58afbee 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,8 @@ * Add network logo's for BBC Canada, Crackle, El Rey Network, SKY Atlantic, and Watch * Change Yahoo! screen network logo +* Change added and updated Discovery Network's channel logo's +* Remove unrequired duplicate network logo's [develop changelog] diff --git a/gui/slick/images/network/aande.png b/gui/slick/images/network/aande.png deleted file mode 100644 index d13b689593162cac494f610b6139a9700edbfe3e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4864 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 diff --git a/gui/slick/images/network/investigation discovery.png b/gui/slick/images/network/investigation discovery.png new file mode 100644 index 0000000000000000000000000000000000000000..084a3153f79d0ddbc3b7967fb19206728a6a2191 GIT binary patch literal 2868 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 BZ#Dn` literal 0 HcmV?d00001 diff --git a/gui/slick/images/network/the hub.png b/gui/slick/images/network/the hub.png new file mode 100644 index 0000000000000000000000000000000000000000..34e5e0fbc1dc15e9fef78841731d8e906051b8e4 GIT binary patch literal 3102 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 literal 0 HcmV?d00001 diff --git a/gui/slick/images/network/the-cw.png b/gui/slick/images/network/the-cw.png deleted file mode 100644 index 67f5abb1a66ae8c669906aaa4cd9ad73729b58f3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3576 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 literal 0 HcmV?d00001 diff --git a/gui/slick/images/network/usa-network.png b/gui/slick/images/network/usa-network.png deleted file mode 100644 index 8bec2afc8664331b0650e4fd2f0532662c1f8d9f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3830 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 diff --git a/gui/slick/images/network/usanetwork.png b/gui/slick/images/network/usanetwork.png deleted file mode 100644 index 8bec2afc8664331b0650e4fd2f0532662c1f8d9f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3830 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 diff --git a/gui/slick/images/network/velocity.png b/gui/slick/images/network/velocity.png new file mode 100644 index 0000000000000000000000000000000000000000..ff4700eeab1244ca0f0c8ed7d91a0a0a45d0a493 GIT binary patch literal 3200 zcmaJ^X*iU7AD$47t%-=SGzLYM8M_&~8EcVcEY;)~GZTYZ%nUP8k|;~I?6O6XBukcq zsA#bqp|TVyp|M3{ZE^ID&Z+Z$czd7gdY=Ds-S_>wf6JFA&e_RUR0t#l002bo?NF}V z)q?wi1^Kz(;{1qc?jpmm_F}kEPBNHS8UbL5r}z@U_9Uzy!Igl;p9=0Gm;eC0U?SR! z;pKQ3fuoSLu-h0d7KzGb0{|xGEGiZkNML|{34TPfDP*bT9t2Fpn?gMG9bt}CB*C9( z7e*tvg*l;dVSzX}9%60=Hen&S0we+h3ucjm$aDnD6!Kjc!QF3PLm}Yr5JsRW7DYr!;eFasFaKwC>&SI^MUPy?(3(}qD|I#6vLO>IMjt_}hQ1OM|txY20% zlL%Lo%|EfYCsT+&gF!_=p-d)Ii>a$cq4`0z;c)o2hK`OV7okZ%MP^`Gnq<1t4+Ru~ zj-wH&3?hXL-d4o=QbHJ}5U$g|Qy@`)%982-l!;p~C<{x4YHPu^Q~CjPbo~EN66q(J z&Tu9C>-T>O)6u7>1gI;4P6?smxQ#ohv>l3yK+*_U28D*EP=bC`(b=EEpwRs(R4~#_ zAM8ma<0(w~ceJA;!k$cLV97XwJ<1fq%o!w`ZoGH z+DI!S10$3*>IWA^!G(|rWX2CJ{$H;3FS*-;K%#OZqX;x&C;@LnqmaPg6Gjk!?S&ip zS6=?+;(zT0`AaU8YX-XA*8ghrk1Ou%Y;S)KE%)$q>7LroUK1}`TJnZG^^S35;nw6x&E!Vn5zH5xgBfi-^J@jM zHtkTMsL95cL1q$xfhwO*7eq%{`bzT$x12x?hrFXT*;RUU1RCaKXM@EAju<5=Y4oJp zlvpa;Lr%6PvBeLk&oomEvXm6^4y1L7y8!Ks!_I7Z;Z1N4I*J@cZ*C3i_8`0WL+nZ;!bO&FaZm%#?cLXKlHu(zgN~ z&~43v2qS0jlBiTFZhzWW1|${pY+NdVSv5c2rV2W4^OK%Ux6FYcXGf}oLG{LTR zL0(2?*0I!8cE3(e$OR8vs_C_gz+QE;!i_j*RmRC$XYhK5I=m>3|Mg_>K1}U3(;TPd zebpe3D@5spm6&#=X6)(q`L#{BoREC9($hX|pU{ZDL29>Y?ZRez)5_k4$cp9%`?S6k zAgL+GTZT4yI?sUQU^btp;+0vS0de{mCw5O|LUC60Y+pcgO*|W3Ts|js;yDvtF&NIP zsd-PB|GYVW&2-iJTk1G13HNG8Up=)Q#(EEBVe;!I+`@r*oB}#qYoU`Z+~`@6kwP-+ z8&%$%NIvaf^@jb1sg~A-ag(_=E@{mv{P>ZLArG6+l%`{hk_hhBCqx-0lF7Tih0tir z+EWFv`DYy~yONWX3wH7IlsO;e2i6>TFmkqCq2}ly87*F>TP)05A4*y&fo>07}cbfLq z=`Z%Gdim6+y@}1cODt1WUM3;B%a^;1mlhJW;uY@CFW(BeukqL#9c`AUp5Md%3TTyq zz55pCa>d-tz@PynFd`>r`^B>0>{)@a-}P-Va&%wJnvcBn#k9 z=E3~719HEGfCD-Xuh5^L5`Gf<$TxU&#Q)s@t^RZZHkT(QRzFH!*?mwjR_o>9VExX` z)q}1T5$;z0nbEppoE4ELoXJPNSVK*?NC)<*9y$WG907bvQb^tqlpETmsMlW&ddLn= zeZh+H4=c&XdR@3E=nKESGj(Y6)iGvWgN=CE5m7mdbWbp?<1Hv&3KSxxc1N+Wa5Jp_ z=IsEzIi22MG2fnOHt|Jjk}~jP;T)zuK$wRr-gol#1jqA`_ejeOt!YD1_%Qmojx~=QBcVavG!aM2*pCNVXGH1-^*vFuF?xSB^{5o8 zWjLe^r!kI|zVs5gVP0{=q19Dwmz4vP$NC-!1VY4zFtO%2#fgiD4gj%qzRu@!GhWN$ zd3S5D22Z^Y1@?J||3%7n#@PCjY81*wS12!zB_Moq@6Xi9Pf)37+iPyK5h>HZxx0jU zX#75;9^dXVRma0SKch5s!`=G$*!Vhc%G@H$WQ)Ie>r}yX^s?4u2c~Azbs3esYQf?D_;*+Alx$QC*cy!6(|>BCd*v=lX-uTIlYKmX)TleR6UwU6Y|-BFkR; zw-ub9=)u3BeFOwoo2b~|gbTh-4oynOiFEv_c|5dd-A?&#nNzFw?;k#n)w6I`z=yq> z5BmRrxHs~MYJu`*!<<&=AW02}y#!9K%RE7^VVInyGBETw{q0FP+e1NVn8aKgP-aM5 z32t_{$ZQ~ekUc%N@;la2@dB;f)E3QWQ}Dx_N{jcPS3v`P#iK3xszlm6pqD|8j%thDAr-H@h z={}^3Ua<`Wx2Egl%fzZr+&^5YqDpsgyd#}yeBsNu-%#%z#)pum-MLFcdj`(zZc3;F zu4h_L3xup+8hu!Tw1VE#M0&Is?472tKoA_{baXO zTdLAqhrFvcLe7FMl&9eO<4Ieq$(pZj$*5Ql?rU|e7<6<@pF&0yQY7Tk+q~I#Z)X)} zItC0K&rXhwTD5KLI|S8y3uqwf1{yyQYq1`bzbQ~kmR7knDlfEiAMbO|Dz?ntIS&>e zT{rt1P$aO^|Js6FS;jeB5W4^1{i_nFlJrbG@jxee*a~w`bEMt~k}t4t^=kTBNn3?e zqpXc^1Hk_4er|5mqx>ev!ClGuob7D#^VmU(#g#yz># ht|yL5k>7-1fa#-XQHgHJ>)ZbX_SR0Q+g3hN{{c+|gR%es literal 0 HcmV?d00001 From c268551c72433b86f3b75ebda6afe971633538ea Mon Sep 17 00:00:00 2001 From: Supremicus Date: Sat, 20 Dec 2014 12:30:58 +1000 Subject: [PATCH 03/21] Add network logos * Add Discovery Network International/A&E Network International/Scripps Networks International missing channel logos --- CHANGES.md | 1 + gui/slick/images/network/cooking channel.png | Bin 0 -> 3003 bytes .../network/crime & investigation network.png | Bin 0 -> 4108 bytes .../network/crime and investigation network.png | Bin 0 -> 4108 bytes gui/slick/images/network/discovery kids.png | Bin 0 -> 6143 bytes gui/slick/images/network/discovery real time.png | Bin 0 -> 2754 bytes gui/slick/images/network/discovery science.png | Bin 0 -> 5545 bytes gui/slick/images/network/food network canada.png | Bin 0 -> 3095 bytes .../images/network/great american country.png | Bin 0 -> 3561 bytes gui/slick/images/network/hgtv canada.png | Bin 0 -> 3167 bytes gui/slick/images/network/hgtv.png | Bin 0 -> 2928 bytes gui/slick/images/network/the science channel.png | Bin 0 -> 5545 bytes 12 files changed, 1 insertion(+) create mode 100644 gui/slick/images/network/cooking channel.png create mode 100644 gui/slick/images/network/crime & investigation network.png create mode 100644 gui/slick/images/network/crime and investigation network.png create mode 100644 gui/slick/images/network/discovery kids.png create mode 100644 gui/slick/images/network/discovery real time.png create mode 100644 gui/slick/images/network/discovery science.png create mode 100644 gui/slick/images/network/food network canada.png create mode 100644 gui/slick/images/network/great american country.png create mode 100644 gui/slick/images/network/hgtv canada.png create mode 100644 gui/slick/images/network/hgtv.png create mode 100644 gui/slick/images/network/the science channel.png diff --git a/CHANGES.md b/CHANGES.md index c58afbee..89d2737b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,6 +4,7 @@ * Change Yahoo! screen network logo * Change added and updated Discovery Network's channel logo's * Remove unrequired duplicate network logo's +* Add Discovery Network International/A&E Network International/Scripps Networks International missing channel logos [develop changelog] diff --git a/gui/slick/images/network/cooking channel.png b/gui/slick/images/network/cooking channel.png new file mode 100644 index 0000000000000000000000000000000000000000..e97314c1e3cbb6af1b831c24f57b0de8153b3c92 GIT binary patch literal 3003 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 literal 0 HcmV?d00001 diff --git a/gui/slick/images/network/crime and investigation network.png b/gui/slick/images/network/crime and investigation network.png new file mode 100644 index 0000000000000000000000000000000000000000..b7394a592caaf2b62311f491d6c55af8a6bd410c GIT binary patch literal 4108 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 literal 0 HcmV?d00001 diff --git a/gui/slick/images/network/discovery kids.png b/gui/slick/images/network/discovery kids.png new file mode 100644 index 0000000000000000000000000000000000000000..81e7063522f0c374b5d7bdea60543adcdf99ceb6 GIT binary patch literal 6143 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 RF2Dc)002ovPDHLkV1l=F+rt0= literal 0 HcmV?d00001 diff --git a/gui/slick/images/network/discovery real time.png b/gui/slick/images/network/discovery real time.png new file mode 100644 index 0000000000000000000000000000000000000000..35ec2bd60a951ed9f211c862a9a88a6bfd4c1ad6 GIT binary patch literal 2754 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 literal 0 HcmV?d00001 diff --git a/gui/slick/images/network/discovery science.png b/gui/slick/images/network/discovery science.png new file mode 100644 index 0000000000000000000000000000000000000000..759dbcd61edc9139c49407a668a5ce8a099629a4 GIT binary patch literal 5545 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 Gg#Q6&7bs!? literal 0 HcmV?d00001 diff --git a/gui/slick/images/network/hgtv canada.png b/gui/slick/images/network/hgtv canada.png new file mode 100644 index 0000000000000000000000000000000000000000..6e64a5d1c8260c52d5a635cbc2a75d99713a0c31 GIT binary patch literal 3167 zcmai02{e>zA0J!c%bIdzxQKt`>Y*uk zZyK56L?#FQtlkNKGL202CkF%3j@m#M0?C&gPTfoF51n`lAq?+}p^%Bd@0rmf{EzqV z${`3XC>nz{N3#9Hp-@v(I2wb|GBwpU(L$Ib5uhJj-@l9c|8c==G2p$j{#TiQZn1l3 zZ~AA`vKN20J)Xqwbqc$w)5_+Q007<*teJ@uePZ$yAvoDZ>fAw)|8Zgc645|mF_C!e zh+a*+Pm-cD{_Z({zll=F`-@WAkM3GK>lfiL?swhLX7GTwK0$mwXMC_h54$Bq>jtSg z)Wx|C&w2!+XjqH7(D*idAY!nwbr6YYn+d*TqydH6d*ZWEk+o-7T>n1O;+7W^cTON$ zjgj=t!acTCVR}{|tHPu3Fgx zbOhURw5f*B*0ss{>dMTcE(0r*eSOyR0+N~@n_?BcZN8q;e2VA0)8pggg(^Io)upAS zKW=_tLdfaUnVgj&ulU8)mjm9mG(UOrP z_1umqb9Q#FCrza)ly!2vmMB~O=}cZsWuJJgP1!Wm5CocKjg7eyUf15YD2oi}zAB$K z)fnEJrR8^bX59k9Xcmj=Gr4D@uBs}$kn`YlW9iyamj~&+nP4j~ue`a11zYYFGDBmWF47@v73QI0v* z7+%5L-Pyiu)Q9{El9`Ww5vH4F&Fo6{qp?P9+#dPQRF9l?Uw=PRWS46=bkF|qcunA| z05`E*$#$Q`W+jme!eUPHd_qDlis~oJRd4BqGFIPka76vKA-g~JVf^&;bdzT@qhCrV z=!TiO`Ibi0)J^R`W%NbC47Sf01yRxK$vYTEJ*}rDdV6lX+7IKp_~~VVMHOLKdDr7J zh;!abIHxAaboj1K@#m$NXs;cZ_#`PmKfeRzYB(csv@$$rNHSJ{XkH97L z@A3ty(|qz@#9zi8K!)`-E+umsqEFto+IPUw_X4NBmdg9U`R5rU!>Z?*)&{lLA1m}Y z#)=lX)dX02sdqkB<0-!O&6c5jUfjw-YSAE8xn}fs=Z^jA<1eyd^RWjGrbFCdIjWSQa9og`h*)IluajOL%VHQ6tuklvq- zsHWT#Zr3Vh)Bc4?QP9X^<#eNth|Kbgi4b@*mD^Y+4vAa!}ZRm1M`Sk&cks% zD*koN?HuOHo;FeMAy7s6g~qAP0f_OC2h8`Gu=9WcA6Z7c2N_?rTF%nAQF=Wox z9~aRTFPG6VIdjt*Ip|6D(TBmVe-Z3$dwYuREE&gd(-`^XfgF+&ZxjR0;CyyK=hpr! z{RMe6XZKDFhs{m6{Zy@Tg3q~WzGMsMAyD4zOhP?R{q(>3?A#s)=et?(TREYR=h)6ii&1~JVeP}OY!!{3&*oHBP04!l3IkDwzoHk72yd&u ze!VhOWTlQA;(xMSn3ZnPx))m=#xAS>aRL6SJCp zu%3DyQv$u)W5`RYO;#)~B+a+EdEa2?u44(e^2uRUgA6YmA439V%#?g<7uV$+k!kUw zV{B31YA}|A>vBC%{91N)S$bYbTtJhwVa#sR^A6p5wcanQQ|_lK9u)~`@Fa#xm`E6> zbYrb^WZDf?*P{XVJ6T8kqdMLV7jNH2MQ&)&>c-@I5+!dxZE++#;o;gZn9e?EYAHZo z%IUHUk?A5yITQ0!Q6FZ_Q{JH4g%l0@J{-4OT?^%1s`@CyOPtm~O!aBoLpOw#V*nEp z`Uh{&*IwkuCCMQj==r8c#zs}5H7F zOX}Jn_S<5jXIsRwht+a^=i$%ht7~d}nwD5B7T)clBZ{^fW@h$$YY1gIiNarGbh~#d z>FkJB!VgO8W~^r=UQSFsSqO1b(1J_z+)r6ILe{}|3JQxdW}5=NE||N|bg;neyOjEl zxNj#_a%dz&xz#BqDR%2i4NFQ0yFae`e#o7ymZkXUgbD44@Vcp|^HMq=mh8)&zV0L% z*4#3Cdu4UtV#E!pdjzB5&q6P%r~2++d6R~C!dUY{kz=r<;Ih^(&v&`mySu2}Isg}7 Yv>|3|d${J(-Y-Aa+}7-Ysn>=70A&D$8UO$Q literal 0 HcmV?d00001 diff --git a/gui/slick/images/network/hgtv.png b/gui/slick/images/network/hgtv.png new file mode 100644 index 0000000000000000000000000000000000000000..86ee82b2804b77ef8146b040a6ca1e3098d90c10 GIT binary patch literal 2928 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 literal 0 HcmV?d00001 diff --git a/gui/slick/images/network/the science channel.png b/gui/slick/images/network/the science channel.png new file mode 100644 index 0000000000000000000000000000000000000000..759dbcd61edc9139c49407a668a5ce8a099629a4 GIT binary patch literal 5545 zcmV;a6;|qrP)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z000WqNkldB;ERIp;m+{@NeF!m_MUR(=^FppcLd2nz&=RX6IIF;Rp> z0~lJdq^W6eI<3=5CTU_iB2c1q`Ug!gkVUH!e=K915J@SMghkeZEMQ$>`L)aL-Mjam zdw#s{+duAIOs2Mz$eMN9XXc%A&zZUB-uL@H&-eL0&m)X6{C_s*a=xsT`h9;R1ylf; z@=5{rZ@&ugfgI3ZUd8hB-^*;<{^J7xaLZ?J0YDo~5EQX+$W*3iY1w4~Y2b<-J9ad6 zb#;BBtE=m(vuDqa>+98!1-JwAEzl-4Cn7QX_V1^io@ zZZxTiYE-Q0?d>6xsX$5>ts`1mb`75g{7=@>vdaZ(4;(nKVArmv?mu?yjVS}Ue3f)1 zQcAo;0?+eEB$Fh(6sc4SDV>@qj%$u}oS50sabkX3+rihDEnD`;xN+kSJ@ef2J$K%9 zSNMMXS8+KUpp^P=9?;slCk0H}ym`}u`}XZ$bne{QI$_y3j)Qa@T-PPxc_dOP(&;qm zbR`uPm88>YGMN;%ZIjOzIMdaMQtGYAlPAA?&plt-1RMtjmMmFf-pvEvYX}S(0M9)8 zi~urW7|wX;8xK8p@L=1tVi-!>wy-P#+cI58eLwOo*9D>f<(e$^ynHUPnp8ZS+l&_ z+WKpr*t&J|_U%vpH8APvr=Lm=RR~x^^q$nwqetib!}q`c_rLnpfvNd?jzVDozmTWs z7YK_*!XTpP2l&2^@B0*sMS?KI_ltyKSh^1a!XUsXg>73@R;Ib~$}70;x>;QN;i)z4 z?MLqW?svbpDVNKAWarKwr#=uI0C@fV{Zk+L-Xo8_^kVDWAP9(}0HrigI#nqpw(TIL zOCp&hok^GDKTSnN1r?Q5R903~U0qF8RaN<#p{lBqR4R=zhQ7Wmr%!ir`0#5alin}C z^u-lluc@gy2ox?S1nh?&e)v5DV2rT_1_tW4ZQJ&Z=XURI0&pA~$Cfy@jb%$5r?h!v z3|cGVC?X6)l+tLUF@O+Y34yR|gb>)agXcQ9o=Y;BB%Mx^N~KDlGa26QJoTaW_Vy`L zCQtfxDwXO1lx11N0zhK_{{2g~Z{Pmse!iHJQX*X!*L87RiRZbvo=54q#Bm&iurOK^ zM=?sp#Id5}g$5xkgk@nn4vt;=j_bN45(z3QDo7+eT+c;1lJ@r3ue{jX?M<6H?SO6D zx%UddgXTpDB0W#*4nOdLf-u|h==aTHM)7yx6?fDi&p7!U#>G?ox0 zwdgo_o<}m7L`sS4c?{$WBX{on$(r@+*Z&51Yd8R?I(F>DlsJk@t}V-_Cxp09o7i;Oy=1{8aF;PS+nWR|G z97bzeTU+O>U%!6zZ~@>J@&hsoLmWq9j3|+q;~;DsQ9e1V>G2sIKW_ZDIFStF=dw(0^7E6q%5aE`w|}%ivi>6>R9>Zd#S0Z;pEAaj2Jlr zDJ8jFj;5xYdFY|_q|<56pFdBbkmpca8w(dUVoc1wSNC$UH;bPy(08#94CW818iyKy zAd|`DdwYA+mi3OF5JHq=Ss;XkZQJkg0fxG|I!2Bh$= zU%_!~EFp;F2&FW!R%9>s(08F5$CbEVQZHY=d|SC}9u_H_oj&6u?b3A-h)byqO2TIF zYFQ;fjIpqUjh9UG=!Q-F=!ZYz&}*+@Sr&IMUqM5|c(U0nS6y`#Qd;!&^%4X@xn?jJ zO(}&&5h%_4#!t1)nKS39%khBA1t3>nU*G0=ou}N z@#vT_V~zvSaD_l|`t<4hKKjvFM_+yQ-==D5>QbdgNe~&sO@DF&j&x~n zZzq$<(An9^p@VI_dEx|DUpNLjGj^X%;V}vSZ%Rg==lTPC}(!b~4d!KA>ZvJPW z8_>gD4a%OLo@+Nex?$t)XLo-pl}S@QVg!jq0^4zTH;pcUD2j;Um?(<4aPAz1LLQ+_ zxw8}yYmIcQl6aCHzV9<)#0dYMFW>v*x^?Tm4ZPLV^x5dS=bjzjhRDq~-V}`*HR|Nz zC5!)Q{Dg+CFbMH|pC~SA{wRumXT{~K)*1l>#UhAOBLuBM8$8#=^CVy)9T%-N^;gvA z9{j7XZ(6r*-M4_wn{T`+VhHTA0nl0l**r4(@-m&i~l zboqV|m@o_piveLVL`N}7E0oq4twDo@z_u(VPMX;Dci;Tx-`suo-H!pC^XAPPvIgm8 z1CUOqx#RZFY2f_o)vGt$dFP$GTh=H})XzWNtmeFQju zb5m0xd$IR}H5r1EFd4Ls8#jh)*RFkY)v8s0>3QC|mX?;!=W_Y#L1{d=j4^~^NFiS! zj>B>vz(NQ?&FInnvp@E+L(QMN{qebT=k5j0&AjgVaNLKk_~4Dk-pw{{+*n+@cI}B3 zD^`3vkw~20vuDrplPCXk(jZe?mW7TrK`}sSh2xY;=9*EXE?zxh!rKcME&SJI%a;8Z zI0Y1D&77%uAMJga3_bD0)@b$WRj2Q` Date: Wed, 17 Dec 2014 18:25:23 +0000 Subject: [PATCH 04/21] Add lowercase PM to the General Config/Interface/Time style selection. Change re-factor sbdatetime classes. Add param "markup" to sbdatetime.sbftime() and sbdatetime.sbfdatetime() that when set True will return time dimensions HTML class wrapped. Add HTML class wrapping to the dimension parser of fuzzy time. Change General Config/Interface/Trim zero padding to Trim date and time, now handles 2:00 pm > 2 pm. Fix trim zero of military time hour to not use 12 hr time. --- CHANGES.md | 11 +- gui/slick/css/dark.css | 5 - gui/slick/css/light.css | 5 - gui/slick/css/style.css | 14 +- .../interfaces/default/config_general.tmpl | 39 +-- gui/slick/js/config.js | 179 ++++++----- gui/slick/js/fuzzyMoment.js | 284 ++++++++++-------- sickbeard/sbdatetime.py | 185 +++++------- 8 files changed, 370 insertions(+), 352 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 89d2737b..ac50f223 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,10 +1,13 @@ ### 0.x.x (2014-12-xx xx:xx:xx UTC) -* Add network logo's for BBC Canada, Crackle, El Rey Network, SKY Atlantic, and Watch +* Add network logos BBC Canada, Crackle, El Rey Network, SKY Atlantic, and Watch * Change Yahoo! screen network logo -* Change added and updated Discovery Network's channel logo's -* Remove unrequired duplicate network logo's -* Add Discovery Network International/A&E Network International/Scripps Networks International missing channel logos +* Add and update Discovery Network's channel logos +* Add A&E Network International/Scripps Networks International channel logos +* Remove non required duplicate network logos +* Add lowercase PM to the General Config/Interface/Time style selection +* Change General Config/Interface/Trim zero padding to Trim date and time, now handles 2:00 pm > 2 pm +* Fix trim zero of military time hour to not use 12 hr time [develop changelog] diff --git a/gui/slick/css/dark.css b/gui/slick/css/dark.css index b78b3bc9..01402916 100644 --- a/gui/slick/css/dark.css +++ b/gui/slick/css/dark.css @@ -1375,11 +1375,6 @@ config*.tmpl padding: 12px 0px; } -#config div.field-pair input { - float: left; - margin-right: 6px; -} - #config .nocheck, #config div #customQuality, .metadataDiv { padding-left: 20px; } diff --git a/gui/slick/css/light.css b/gui/slick/css/light.css index 416ec481..b5b79722 100644 --- a/gui/slick/css/light.css +++ b/gui/slick/css/light.css @@ -1358,11 +1358,6 @@ config*.tmpl padding: 12px 0px; } -#config div.field-pair input { - float: left; - margin-right: 6px; -} - #config .nocheck, #config div #customQuality, .metadataDiv { padding-left: 20px; } diff --git a/gui/slick/css/style.css b/gui/slick/css/style.css index 7c00de52..bd02c682 100644 --- a/gui/slick/css/style.css +++ b/gui/slick/css/style.css @@ -153,7 +153,7 @@ inc_top.tmpl /* background: url("../images/bg.png") repeat 0 0 transparent; */ } -[class^="icon-"], +[class^="icon-"], [class*=" icon-"] { background-image: url("../images/glyphicons-halflings.png"); } @@ -1591,10 +1591,13 @@ config*.tmpl padding: 12px 0 } -.stepDiv .component-desc select, -.stepDiv .component-desc input, #config div.field-pair select, #config div.field-pair input { + margin-right: 6px; +} + +.stepDiv .component-desc select, +.stepDiv .component-desc input { margin-right: 15px; } @@ -3153,6 +3156,11 @@ span.token-input-delete-token { z-index: 0; background-image: url(../images/poster-dark.jpg) } + +.time-am-pm { + margin-left: 2px; +} + /* ======================================================================= jquery.confirm.css ========================================================================== */ diff --git a/gui/slick/interfaces/default/config_general.tmpl b/gui/slick/interfaces/default/config_general.tmpl index 02e2a74c..2817d0e0 100644 --- a/gui/slick/interfaces/default/config_general.tmpl +++ b/gui/slick/interfaces/default/config_general.tmpl @@ -103,9 +103,9 @@ as the default selection when adding new shows @@ -127,7 +127,7 @@ Show root directories

where the files of shows are located

- #include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_rootDirs.tmpl') +#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_rootDirs.tmpl')
@@ -246,10 +246,10 @@
@@ -259,16 +259,16 @@ Date style: @@ -279,11 +279,12 @@ Time style: - note: seconds are only shown on the History page + note: seconds are only shown on the History page @@ -450,9 +451,9 @@ Branch version:

select branch to use (restart required)

@@ -485,9 +486,9 @@ CPU throttling: Normal (default). High is lower and Low is higher CPU use diff --git a/gui/slick/js/config.js b/gui/slick/js/config.js index e908b0f8..41046e69 100644 --- a/gui/slick/js/config.js +++ b/gui/slick/js/config.js @@ -1,85 +1,126 @@ $(document).ready(function(){ - $('.enabler').each(function(){ - if (!$(this).prop('checked')) - $('#content_' + $(this).attr('id')).hide(); - }); + var enabler = $('.enabler'), + viewIf = $('.viewIf'); - $('.enabler').click(function(){ - if ($(this).prop('checked')) - $('#content_' + $(this).attr('id')).fadeIn('fast', 'linear'); - else - $('#content_' + $(this).attr('id')).fadeOut('fast', 'linear'); - }); + enabler.each(function(){ + if (!$(this).prop('checked')) + $('#content_' + $(this).attr('id')).hide(); + }); - $('.viewIf').click(function(){ - if ($(this).prop('checked')) { - $('.hide_if_' + $(this).attr('id')).css('display','none'); - $('.show_if_' + $(this).attr('id')).fadeIn('fast', 'linear'); - } else { - $('.show_if_' + $(this).attr('id')).css('display','none'); - $('.hide_if_' + $(this).attr('id')).fadeIn('fast', 'linear'); - } - }); + enabler.click(function(){ + var content_id = $('#content_' + $(this).attr('id')); + if ($(this).prop('checked')) + content_id.fadeIn('fast', 'linear'); + else + content_id.fadeOut('fast', 'linear'); + }); - $('.datePresets').click(function(){ - var def = $('#date_presets').val() - if ($(this).prop('checked') && '%x' == def) { - def = '%a, %b %d, %Y' - $('#date_use_system_default').html('1') - } else if (!$(this).prop('checked') && '1' == $('#date_use_system_default').html()) - def = '%x' + viewIf.each(function(){ + $(($(this).prop('checked') ? '.hide_if_' : '.show_if_') + $(this).attr('id')).hide(); + }); - $('#date_presets').attr('name', 'date_preset_old') - $('#date_presets').attr('id', 'date_presets_old') + viewIf.click(function(){ + var if_id = '_if_' + $(this).attr('id'); + if ($(this).prop('checked')) { + $('.hide' + if_id).fadeOut('fast', 'linear'); + $('.show' + if_id).fadeIn('fast', 'linear'); + } else { + $('.show' + if_id).fadeOut('fast', 'linear'); + $('.hide' + if_id).fadeIn('fast', 'linear'); + } + }); - $('#date_presets_na').attr('name', 'date_preset') - $('#date_presets_na').attr('id', 'date_presets') + var ui_update_trim_zero = (function() { + var secs = ('00' + new Date().getSeconds().toString()).slice(-2), + elSecs = $('#trim_info_seconds'), + elTrimZero = $('#trim_zero'); + elTrimZero.each(function() { + var checked = $(this).prop('checked') && $('#fuzzy_dating').prop('checked'); - $('#date_presets_old').attr('name', 'date_preset_na') - $('#date_presets_old').attr('id', 'date_presets_na') + $('#time_presets').find('option').each(function() { + var text = ($(this).text()); + $(this).text(checked + ? text.replace(/(\b\d+:\d\d):\d+/mg, '$1') + : text.replace(/(\b\d+:\d\d)(?:.\d+)?/mg, '$1:' + secs)); + }); + }); - if (def) - $('#date_presets').val(def) - }); + if ($('#fuzzy_dating').prop('checked')) + if (elTrimZero.prop('checked')) + elSecs.fadeOut('fast', 'linear'); + else + elSecs.fadeIn('fast', 'linear'); + else + elSecs.fadeIn('fast', 'linear'); + }); - // bind 'myForm' and provide a simple callback function - $('#configForm').ajaxForm({ - beforeSubmit: function(){ - $('.config_submitter').each(function(){ - $(this).attr('disabled', 'disabled'); - $(this).after(' Saving...'); - $(this).hide(); - }); - }, - success: function(){ - setTimeout('config_success()', 2000) - } - }); + $('#trim_zero, #fuzzy_dating').click(function() { + ui_update_trim_zero(); + }); - $('#api_key').click(function(){ $('#api_key').select() }); - $("#generate_new_apikey").click(function(){ - $.get(sbRoot + '/config/general/generateKey', - function(data){ - if (data.error != undefined) { - alert(data.error); - return; - } - $('#api_key').val(data); - }); - }); + ui_update_trim_zero(); - $('#branchCheckout').click(function(){ - url = sbRoot + '/home/branchCheckout?branch=' + $('#branchVersion').val(); - window.location.href = url; - }); + $('.datePresets').click(function(){ + var elDatePresets = $('#date_presets'), + defaultPreset = elDatePresets.val(); + if ($(this).prop('checked') && '%x' == defaultPreset) { + defaultPreset = '%a, %b %d, %Y'; + $('#date_use_system_default').html('1') + } else if (!$(this).prop('checked') && '1' == $('#date_use_system_default').html()) + defaultPreset = '%x'; + + elDatePresets.attr('name', 'date_preset_old'); + elDatePresets.attr('id', 'date_presets_old'); + + var elDatePresets_na = $('#date_presets_na'); + elDatePresets_na.attr('name', 'date_preset'); + elDatePresets_na.attr('id', 'date_presets'); + + var elDatePresets_old = $('#date_presets_old'); + elDatePresets_old.attr('name', 'date_preset_na'); + elDatePresets_old.attr('id', 'date_presets_na'); + + if (defaultPreset) + elDatePresets.val(defaultPreset) + }); + + // bind 'myForm' and provide a simple callback function + $('#configForm').ajaxForm({ + beforeSubmit: function(){ + $('.config_submitter').each(function(){ + $(this).attr('disabled', 'disabled'); + $(this).after(' Saving...'); + $(this).hide(); + }); + }, + success: function(){ + setTimeout('config_success()', 2000) + } + }); + + $('#api_key').click(function(){ $('#api_key').select() }); + $("#generate_new_apikey").click(function(){ + $.get(sbRoot + '/config/general/generateKey', + function(data){ + if (data.error != undefined) { + alert(data.error); + return; + } + $('#api_key').val(data); + }); + }); + + $('#branchCheckout').click(function(){ + window.location.href = sbRoot + '/home/branchCheckout?branch=' + $('#branchVersion').val(); + }); }); function config_success(){ - $('.config_submitter').each(function(){ - $(this).removeAttr('disabled'); - $(this).next().remove(); - $(this).show(); - }); - $('#email_show').trigger('notify'); + $('.config_submitter').each(function(){ + $(this).removeAttr('disabled'); + $(this).next().remove(); + $(this).show(); + }); + $('#email_show').trigger('notify'); } diff --git a/gui/slick/js/fuzzyMoment.js b/gui/slick/js/fuzzyMoment.js index dc81c399..ab319f94 100644 --- a/gui/slick/js/fuzzyMoment.js +++ b/gui/slick/js/fuzzyMoment.js @@ -11,152 +11,170 @@ */ function fuzzyMoment(fmConfig) { - var containerClass = (/undefined/i.test(typeof(fmConfig)) || /undefined/i.test(typeof(fmConfig.containerClass)) ? '.fuzzydate' : fmConfig.containerClass), - dateWithTime = (/undefined/i.test(typeof(fmConfig)) || /undefined/i.test(typeof(fmConfig.dateHasTime)) ? false : !!fmConfig.dateHasTime), - dateFormat = (/undefined/i.test(typeof(fmConfig)) || /undefined/i.test(typeof(fmConfig.dateFormat)) ? '' : fmConfig.dateFormat), - timeFormat = (/undefined/i.test(typeof(fmConfig)) || /undefined/i.test(typeof(fmConfig.timeFormat)) ? '' : fmConfig.timeFormat), - trimZero = (/undefined/i.test(typeof(fmConfig)) || /undefined/i.test(typeof(fmConfig.trimZero)) ? false : !!fmConfig.trimZero), - dtGlue = (/undefined/i.test(typeof(fmConfig)) || /undefined/i.test(typeof(fmConfig.dtGlue)) ? '
' : fmConfig.dtGlue), - dtInline = (/undefined/i.test(typeof(fmConfig)) || /undefined/i.test(typeof(fmConfig.dtInline)) ? false : fmConfig.dtInline), + var containerClass = (/undefined/i.test(typeof(fmConfig)) || /undefined/i.test(typeof(fmConfig.containerClass)) ? '.fuzzydate' : fmConfig.containerClass), + dateWithTime = (/undefined/i.test(typeof(fmConfig)) || /undefined/i.test(typeof(fmConfig.dateHasTime)) ? false : !!fmConfig.dateHasTime), + dateFormat = (/undefined/i.test(typeof(fmConfig)) || /undefined/i.test(typeof(fmConfig.dateFormat)) ? '' : fmConfig.dateFormat), + timeFormat = (/undefined/i.test(typeof(fmConfig)) || /undefined/i.test(typeof(fmConfig.timeFormat)) ? '' : fmConfig.timeFormat), + trimZero = (/undefined/i.test(typeof(fmConfig)) || /undefined/i.test(typeof(fmConfig.trimZero)) ? false : !!fmConfig.trimZero), + dtGlue = (/undefined/i.test(typeof(fmConfig)) || /undefined/i.test(typeof(fmConfig.dtGlue)) ? '
' : fmConfig.dtGlue), + dtInline = (/undefined/i.test(typeof(fmConfig)) || /undefined/i.test(typeof(fmConfig.dtInline)) ? false : fmConfig.dtInline), - jd = (function (str) { - var token_map = ['a', 'ddd', 'A', 'dddd', 'b', 'MMM', 'B', 'MMMM', 'd', 'DD', 'm', 'MM', 'y', 'YY', 'Y', 'YYYY', 'x', 'L', - 'H', 'HH', 'I', 'hh', 'M', 'mm', 'S', 'ss', 'p', 'A'], - result = ''; + jd = (function (str) { + var token_map = ['a', 'ddd', 'A', 'dddd', 'b', 'MMM', 'B', 'MMMM', 'd', 'DD', 'm', 'MM', 'y', 'YY', 'Y', 'YYYY', 'x', 'L', + 'H', 'HH', 'I', 'hh', 'M', 'mm', 'S', 'ss', 'p', 'A', 'P', 'a'], + result = ''; - for (var i = 0; i < str.length; i++) - if (/[aAbBdmyYxHIMSp]/.test(str[i])) { - for (var t = 0; t < token_map.length; t = t + 2) - if (str[i] == token_map[t]) { - result += token_map[t + 1]; - break; - } - } else if ('%' != str[i]) - result += str[i]; + for (var i = 0; i < str.length; i++) + if (/[aAbBdmyYxHIMSpP]/.test(str[i])) { + for (var t = 0; t < token_map.length; t = t + 2) + if (str[i] == token_map[t]) { + result += token_map[t + 1]; + break; + } + } else if ('%' != str[i]) + result += str[i]; - return result; - }), - dateToken = jd(dateFormat), - timeToken = jd(timeFormat), + return result; + }), + dateTemplate = jd(dateFormat), + timeTemplate = jd(timeFormat), - addQTip = (function() { - $(this).css('cursor', 'help'); - $(this).qtip({ - show: { - solo: true - }, - position: { - viewport: $(window), - my: 'left center', - adjust: { - y: -10, - x: 2 - } - }, - style: { - classes: 'qtip-dark qtip-rounded qtip-shadow' - } - }); - }); + addQTip = (function() { + $(this).css('cursor', 'help'); + $(this).qtip({ + show: { + solo: true + }, + position: { + viewport: $(window), + my: 'left center', + adjust: { + y: -10, + x: 2 + } + }, + style: { + classes: 'qtip-dark qtip-rounded qtip-shadow' + } + }); + }); - if (trimZero) { - timeToken = timeToken.replace(/hh/ig, 'h'); - dateToken = dateToken.replace(/\bDD\b/g, 'D'); - } + if (trimZero) { + timeTemplate = timeTemplate.replace(/hh/g, 'h'); + timeTemplate = timeTemplate.replace(/HH/g, 'H'); + dateTemplate = dateTemplate.replace(/\bDD\b/g, 'D'); + } - $(containerClass).each(function() { - var input = $(this).text(), - dateA = '[', - dtSeparator = ' ', - timeA = ']', timeB = '[' + timeA; + $(containerClass).each(function() { + var input = $(this).text(), + dateA = '[', + dtSeparator = ' ', + timeA = ']', timeB = '[' + timeA, + timeToken = timeTemplate; - if (dateWithTime) { - var timeMeta = input.match(/^.{6,}?([,\s]+)(\d{1,2}).(?:\d{2,2})(?:.(\d{2,2}))?(?:\s([ap]m))?$/im); - if (null != timeMeta) { - dtSeparator = (! /undefined/i.test(typeof(timeMeta[1])) ? timeMeta[1] : dtSeparator); - // adjust timeToken to num digits of input hours - timeToken = (! /undefined/i.test(typeof(timeMeta[2])) && 1 == timeMeta[2].length ? timeToken.replace(/hh/ig, 'h') : timeToken); - // adjust timeToken to use seconds if input has them - timeToken = (! /undefined/i.test(typeof(timeMeta[3])) && 2 == timeMeta[3].length ? timeToken : timeToken.replace(/.ss/, '')); - // adjust timeToken to am/pm or AM/PM if input has it - timeToken = (! /undefined/i.test(typeof(timeMeta[4])) && 2 == timeMeta[4].length ? timeToken.replace(/A$/, (/[ap]m/.test(timeMeta[4]) ? 'a' : 'A')) : timeToken); - } - timeA = '
' + dtGlue + ']' + timeToken + '[' + timeA; - timeB = '[' + dtGlue + ']' + timeToken + timeB; - } + if (dateWithTime) { + var timeMeta = input.match(/([,\s]+)(\d{1,2})(?:(.)(\d\d)(?:(.)(\d\d))?)?(?:\s?([ap]m))?$/im); + if (null != timeMeta) { + dtSeparator = (! /undefined/i.test(typeof(timeMeta[1])) ? timeMeta[1] : dtSeparator); + // adjust timeToken to num digits of input hours + timeToken = (! /undefined/i.test(typeof(timeMeta[2])) && 1 == timeMeta[2].length ? timeToken.replace(/hh/ig, 'h') : timeToken); + // adjust timeToken to remove min if input has one and there is a pm + timeToken = (trimZero && ! /undefined/i.test(typeof(timeMeta[7])) + && (/undefined/i.test(typeof(timeMeta[4])) + || '00' == timeMeta[4]) ? timeToken.replace(/.mm/ig, '') : timeToken); + // adjust timeToken to use seconds if input has them + timeToken = (! /undefined/i.test(typeof(timeMeta[5])) && 2 == timeMeta[5].length ? timeToken : timeToken.replace(/.ss/, '')); + // adjust timeToken to am/pm or AM/PM if input has it + timeToken = (! /undefined/i.test(typeof(timeMeta[7])) && 2 == timeMeta[7].length ? timeToken.replace(/A$/, (/[ap]m/.test(timeMeta[7]) ? 'a' : 'A')) : timeToken); + } - var inputTokens = dateToken + dtSeparator + (dateWithTime ? timeToken : 'HH:mm:ss'); + var token_build = (/h+/i.test(timeToken) ? timeToken.replace(/^(h+).*/i, '[]$1[]') : ''); + if (/m+/i.test(timeToken)) { + token_build += (! /undefined/i.test(typeof(timeMeta[3])) ? '[]' + timeMeta[3] + '[]' : '') + + (! /undefined/i.test(typeof(timeMeta[4])) ? timeToken.replace(/.*?(m+).*/i, '[]$1[]') : ''); + if (/s+/i.test(timeToken)) { + token_build += (! /undefined/i.test(typeof(timeMeta[5])) ? '[]' + timeMeta[5] + '[]' : '') + + (! /undefined/i.test(typeof(timeMeta[6])) ? timeToken.replace(/.*?(s+).*/i, '[]$1[]') : ''); + } + } + timeToken = token_build + (! /undefined/i.test(typeof(timeMeta[7])) ? timeToken.replace(/.*?[\s0-9](a).*/i, '[]$1[]') : ''); - if (! moment(input + (dateWithTime ? '' : dtSeparator + '00:00:00'), inputTokens).isValid()) - return; + timeA = '' + dtGlue + ']' + timeToken + '[' + timeA; + timeB = '[' + dtGlue + ']' + timeToken + timeB; + } - moment.lang('en', { - calendar: { - lastDay:dateA + 'Yesterday' + timeA, sameDay:dateA + 'Today' + timeA, nextDay:dateA + 'Tomorrow' + timeA, - lastWeek:dateA + 'last] ddd' + timeB, nextWeek:dateA + 'on] ddd' + timeB, - sameElse:dateA + ']ddd, MMM D YYYY[' + timeA - }, - relativeTime: { - future:'in %s', past:'%s ago', s:'seconds', m:'a minute', mm:'%d minutes', h:'an hour', hh:'%d hours', - d:'a day', dd:'%d days', M:'a month', MM:'%d months', y:'a year', yy:'%d years' - } - }); + var inputTokens = dateTemplate + dtSeparator + (dateWithTime ? timeToken : 'HH:mm:ss'); - var airdatetime = moment(input + (dateWithTime ? '' : dtSeparator + '00:00:00'), inputTokens), - airdate = airdatetime.clone().hour(0).minute(0).second(0).millisecond(0), - today = moment({}), - day = Math.abs(airdate.diff(today, 'days')), - week = Math.abs(weekdiff = airdate.diff(today, 'week')), isPast = weekdiff < 0, - titleThis = false, qTipTime = false, - result = (0 == week ? airdatetime.calendar() : ''); + if (! moment(input + (dateWithTime ? '' : dtSeparator + '00:00:00'), inputTokens).isValid()) + return; - if (/\bOn\b/i.test(result)) { - var fuzzer = false, weekday = today.day(); - if (3 == weekday) - fuzzer = (5 <= day); - else if (4 == weekday || 5 == weekday) - fuzzer = (4 <= day); - else - fuzzer = (6 == day); - if (fuzzer) - result = result.replace(/\bOn\b/i, 'Next'); + moment.lang('en', { + calendar: { + lastDay:dateA + 'Yesterday' + timeA, sameDay:dateA + 'Today' + timeA, nextDay:dateA + 'Tomorrow' + timeA, + lastWeek:dateA + 'last] ddd' + timeB, nextWeek:dateA + 'on] ddd' + timeB, + sameElse:dateA + ']ddd, MMM D YYYY[' + timeA + }, + relativeTime: { + future:'in %s', past:'%s ago', s:'seconds', m:'a minute', mm:'%d minutes', h:'an hour', hh:'%d hours', + d:'a day', dd:'%d days', M:'a month', MM:'%d months', y:'a year', yy:'%d years' + } + }); - } else if (! /\b((yester|to)day\b|tomo|last\b)/i.test(result)) { - if (14 > day) - result = airdate.from(today) + (dateWithTime ? dtGlue + airdatetime.format(timeToken) : ''); - else if (4 > week) { - result = (isPast ? '' : 'in ') + (1 == week ? 'a' : week) + ' week' + (1 == week ? '' : 's') + (isPast ? ' ago' : ''); - qTipTime = true; - } else { - result = airdate.from(today); - qTipTime = true; - var month = airdate.diff(today, 'month'); - if (1 == parseInt(airdate.year() - today.year())) - result += (dtInline ? ' ' : '
') + '(Next Year)'; - } - titleThis = true; - } + var airdatetime = moment(input + (dateWithTime ? '' : dtSeparator + '00:00:00'), inputTokens), + airdate = airdatetime.clone().hour(0).minute(0).second(0).millisecond(0), + today = moment({}), + day = Math.abs(airdate.diff(today, 'days')), + week = Math.abs(weekdiff = airdate.diff(today, 'week')), isPast = weekdiff < 0, + titleThis = false, qTipTime = false, + result = (0 == week ? airdatetime.calendar() : ''); - var n = false; // disable for prod - $(this).html(result); - if (dateWithTime && /(yester|to)day/i.test(result)) - $(this).find('.fd').attr('title',(n?'1) ':'') + moment.duration(airdatetime.diff(moment(),'seconds'),'seconds').humanize(true)).each(addQTip); - else if (dateWithTime) - $(this).find('.fd').attr('title',(n?'2) ':'') + airdate.from(today)).each(addQTip); - else if (! /today/i.test(result)) - $(this).find('.fd').attr('title',(n?'3) ':'') + airdate.from(today)).each(addQTip); - else - titleThis = false; + if (/\bOn\b/i.test(result)) { + var fuzzer = false, weekday = today.day(); + if (3 == weekday) + fuzzer = (5 <= day); + else if (4 == weekday || 5 == weekday) + fuzzer = (4 <= day); + else + fuzzer = (6 == day); + if (fuzzer) + result = result.replace(/\bOn\b/i, 'Next'); - if (titleThis) - if (dateWithTime && qTipTime) - $(this).attr('title',(n?'4) ':'') + airdatetime.format(inputTokens)).each(addQTip); - else - $(this).attr('title',(n?'5) ':'') + airdate.format(dateToken)).each(addQTip); - else - if (dateWithTime && qTipTime) - $(this).find('.ft').attr('title',(n?'6) ':'') + airdatetime.format(inputTokens)).each(addQTip); - else - $(this).find('.ft').attr('title',(n?'7) ':'') + airdate.format(dateToken)).each(addQTip); - }); + } else if (! /\b((yester|to)day\b|tomo|last\b)/i.test(result)) { + if (14 > day) + result = airdate.from(today) + (dateWithTime ? dtGlue + airdatetime.format(timeToken) : ''); + else if (4 > week) { + result = (isPast ? '' : 'in ') + (1 == week ? 'a' : week) + ' week' + (1 == week ? '' : 's') + (isPast ? ' ago' : ''); + qTipTime = true; + } else { + result = airdate.from(today); + qTipTime = true; + var month = airdate.diff(today, 'month'); + if (1 == parseInt(airdate.year() - today.year())) + result += (dtInline ? ' ' : '
') + '(Next Year)'; + } + titleThis = true; + } + + var n = false; // disable for prod + $(this).html(result); + if (dateWithTime && /(yester|to)day/i.test(result)) + $(this).find('.fd').attr('title',(n?'1) ':'') + moment.duration(airdatetime.diff(moment(),'seconds'),'seconds').humanize(true)).each(addQTip); + else if (dateWithTime) + $(this).find('.fd').attr('title',(n?'2) ':'') + airdate.from(today)).each(addQTip); + else if (! /today/i.test(result)) + $(this).find('.fd').attr('title',(n?'3) ':'') + airdate.from(today)).each(addQTip); + else + titleThis = false; + + if (titleThis) + if (dateWithTime && qTipTime) + $(this).attr('title',(n?'4) ':'') + airdatetime.format(inputTokens)).each(addQTip); + else + $(this).attr('title',(n?'5) ':'') + airdate.format(dateTemplate)).each(addQTip); + else + if (dateWithTime && qTipTime) + $(this).find('.ft').attr('title',(n?'6) ':'') + airdatetime.format(inputTokens)).each(addQTip); + else + $(this).find('.ft').attr('title',(n?'7) ':'') + airdate.format(dateTemplate)).each(addQTip); + }); } diff --git a/sickbeard/sbdatetime.py b/sickbeard/sbdatetime.py index 5e96f667..9f49b865 100644 --- a/sickbeard/sbdatetime.py +++ b/sickbeard/sbdatetime.py @@ -19,6 +19,7 @@ import datetime import locale import functools +import re import sickbeard from sickbeard.network_timezones import sb_timezone @@ -82,12 +83,12 @@ date_presets = ('%Y-%m-%d', '%A, %b %d, %Y', '%B %d, %Y', '%a, %B %d, %Y', - '%A, %B %d, %Y' -) + '%A, %B %d, %Y') time_presets = ('%I:%M:%S %p', - '%H:%M:%S' -) + '%I:%M:%S %P', + '%H:%M:%S') + # helper class class static_or_instance(object): @@ -104,142 +105,98 @@ class sbdatetime(datetime.datetime): @static_or_instance def convert_to_setting(self, dt=None): + obj = (dt, self)[self is not None] try: - if sickbeard.TIMEZONE_DISPLAY == 'local': - if self is None: - return dt.astimezone(sb_timezone) - else: - return self.astimezone(sb_timezone) - else: - if self is None: - return dt - else: - return self + if 'local' == sickbeard.TIMEZONE_DISPLAY: + return obj.astimezone(sb_timezone) except: - if self is None: - return dt - else: - return self + pass + + return obj + + @static_or_instance + def setlocale(self, setlocale=True, use_has_locale=None, locale_str=''): + if setlocale: + try: + if None is use_has_locale or use_has_locale: + locale.setlocale(locale.LC_TIME, locale_str) + except: + if None is not use_has_locale: + sbdatetime.has_locale = False + pass # display Time in SickGear Format @static_or_instance - def sbftime(self, dt=None, show_seconds=False, t_preset=None): + def sbftime(self, dt=None, show_seconds=False, t_preset=None, setlocale=True, markup=False): - try:locale.setlocale(locale.LC_TIME, '') - except:pass - - try: - if sbdatetime.has_locale: - locale.setlocale(locale.LC_TIME, 'us_US') - except: - sbdatetime.has_locale = False + sbdatetime.setlocale(setlocale=setlocale, use_has_locale=sbdatetime.has_locale, locale_str='us_US') strt = '' try: - if self is None: - if dt is not None: - if t_preset is not None: - strt = dt.strftime(t_preset) - elif show_seconds: - strt = dt.strftime(sickbeard.TIME_PRESET_W_SECONDS) - else: - strt = dt.strftime(sickbeard.TIME_PRESET) - else: - if t_preset is not None: - strt = self.strftime(t_preset) - elif show_seconds: - strt = self.strftime(sickbeard.TIME_PRESET_W_SECONDS) - else: - strt = self.strftime(sickbeard.TIME_PRESET) - finally: - try: - if sbdatetime.has_locale: - locale.setlocale(locale.LC_TIME, '') - except: - sbdatetime.has_locale = False + obj = (dt, self)[self is not None] + if None is not obj: + tmpl = (((sickbeard.TIME_PRESET, sickbeard.TIME_PRESET_W_SECONDS)[show_seconds]), + t_preset)[None is not t_preset] + tmpl = (tmpl.replace(':%S', ''), tmpl)[show_seconds] + strt = obj.strftime(tmpl.replace('%P', '%p')) + + if sickbeard.TRIM_ZERO: + strt = re.sub(r'^0(\d:\d\d)', r'\1', strt) + + if re.search(r'(?im)%p$', tmpl): + if '%p' in tmpl: + strt = strt.upper() + elif '%P' in tmpl: + strt = strt.lower() + + if sickbeard.TRIM_ZERO: + strt = re.sub(r'(?im)^(\d+)(?::00)?(\s?[ap]m)', r'\1\2', strt) + + if markup: + match = re.search(r'(?im)(\d{1,2})(?:(.)(\d\d)(?:(.)(\d\d))?)?(?:\s?([ap]m))?$', strt) + if match: + strt = ('%s%s%s%s%s%s' % ( + ('%s' % match.group(1), '')[None is match.group(1)], + ('%s' % match.group(2), '')[None is match.group(2)], + ('%s' % match.group(3), '')[None is match.group(3)], + ('%s' % match.group(4), '')[None is match.group(4)], + ('%s' % match.group(5), '')[None is match.group(5)], + ('%s' % match.group(6), '')[None is match.group(6)])) + + finally: + sbdatetime.setlocale(setlocale=setlocale, use_has_locale=sbdatetime.has_locale) return strt # display Date in SickGear Format @static_or_instance - def sbfdate(self, dt=None, d_preset=None): + def sbfdate(self, dt=None, d_preset=None, setlocale=True): - try: - locale.setlocale(locale.LC_TIME, '') - except: - pass + sbdatetime.setlocale(setlocale=setlocale) strd = '' try: - if self is None: - if dt is not None: - if d_preset is not None: - strd = dt.strftime(d_preset) - else: - strd = dt.strftime(sickbeard.DATE_PRESET) - else: - if d_preset is not None: - strd = self.strftime(d_preset) - else: - strd = self.strftime(sickbeard.DATE_PRESET) + obj = (dt, self)[self is not None] + if None is not obj: + strd = obj.strftime((sickbeard.DATE_PRESET, d_preset)[None is not d_preset]) + finally: - - try: - locale.setlocale(locale.LC_TIME, '') - except: - pass - + sbdatetime.setlocale(setlocale=setlocale) return strd # display Datetime in SickGear Format @static_or_instance - def sbfdatetime(self, dt=None, show_seconds=False, d_preset=None, t_preset=None): + def sbfdatetime(self, dt=None, show_seconds=False, d_preset=None, t_preset=None, markup=False): - try: - locale.setlocale(locale.LC_TIME, '') - except: - pass + sbdatetime.setlocale() strd = '' + obj = (dt, self)[self is not None] try: - if self is None: - if dt is not None: - if d_preset is not None: - strd = dt.strftime(d_preset) - else: - strd = dt.strftime(sickbeard.DATE_PRESET) - try: - if sbdatetime.has_locale: - locale.setlocale(locale.LC_TIME, 'us_US') - except: - sbdatetime.has_locale = False - if t_preset is not None: - strd += u', ' + dt.strftime(t_preset) - elif show_seconds: - strd += u', ' + dt.strftime(sickbeard.TIME_PRESET_W_SECONDS) - else: - strd += u', ' + dt.strftime(sickbeard.TIME_PRESET) - else: - if d_preset is not None: - strd = self.strftime(d_preset) - else: - strd = self.strftime(sickbeard.DATE_PRESET) - try: - if sbdatetime.has_locale: - locale.setlocale(locale.LC_TIME, 'us_US') - except: - sbdatetime.has_locale = False - if t_preset is not None: - strd += u', ' + self.strftime(t_preset) - elif show_seconds: - strd += u', ' + self.strftime(sickbeard.TIME_PRESET_W_SECONDS) - else: - strd += u', ' + self.strftime(sickbeard.TIME_PRESET) - finally: - try: - if sbdatetime.has_locale: - locale.setlocale(locale.LC_TIME, '') - except: - sbdatetime.has_locale = False + if None is not obj: + strd = u'%s, %s' % (obj.strftime((sickbeard.DATE_PRESET, d_preset)[None is not d_preset]), + sbdatetime.sbftime(dt, show_seconds, t_preset, False, markup)) + finally: + sbdatetime.setlocale(use_has_locale=sbdatetime.has_locale) return strd From 7b3499f9582395b064f373513d82750948e38886 Mon Sep 17 00:00:00 2001 From: Supremicus Date: Mon, 22 Dec 2014 17:47:11 +1000 Subject: [PATCH 05/21] Change ThePirateBay to use oldpiratebay * Change ThePirateBay to use oldpiratebay as a temporary fix --- CHANGES.md | 1 + sickbeard/providers/thepiratebay.py | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 332aabf8..8fcb0cc3 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,6 +8,7 @@ * Add lowercase PM to the General Config/Interface/Time style selection * Change General Config/Interface/Trim zero padding to Trim date and time, now handles 2:00 pm > 2 pm * Fix trim zero of military time hour to not use 12 hr time +* Change ThePirateBay to use oldpiratebay as a temporary fix [develop changelog] diff --git a/sickbeard/providers/thepiratebay.py b/sickbeard/providers/thepiratebay.py index 954f4dcc..4cb5e388 100644 --- a/sickbeard/providers/thepiratebay.py +++ b/sickbeard/providers/thepiratebay.py @@ -61,11 +61,11 @@ class ThePirateBayProvider(generic.TorrentProvider): self.proxy = ThePirateBayWebproxy() - self.url = 'http://pirateproxy.net/' + self.url = 'http://oldpiratebay.org/' - self.searchurl = self.url + 'search/%s/0/7/200' # order by seed + self.searchurl = self.url + 'search.php?q=%s&Torrent_sort=seeders.desc' # order by seed - self.re_title_url = '/torrent/(?P\d+)/(?P.*?)//1".+?(?P<url>magnet.*?)//1".+?(?P<seeders>\d+)</td>.+?(?P<leechers>\d+)</td>' + self.re_title_url = 'href=["\'](?P<url>magnet:.*?)&.*?/torrent/(?P<id>\d+)/(?P<title>.*?)".+?seeders-row sy">(?P<seeders>\d+)</td>.+?leechers-row ly">(?P<leechers>\d+)</td>' def isEnabled(self): return self.enabled From 2e382c2010d95b47cb84b8883639592ce8345d43 Mon Sep 17 00:00:00 2001 From: Sami Haahtinen <sami@badwolf.fi> Date: Wed, 24 Dec 2014 12:08:15 +0200 Subject: [PATCH 06/21] Change Search Settings/Torrent/Deluge option texts for improved understanding Deluge uses WebUI to connect to deluge daemon, lets make sure that the user knows what to enter. Also the WebUI doesn't use a username at all, so we can hide that field so that the user doesn't get confused --- CHANGES.md | 1 + gui/slick/interfaces/default/config_search.tmpl | 3 ++- gui/slick/js/configSearch.js | 5 +++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index bbe45cb4..6be107da 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -9,6 +9,7 @@ * Change General Config/Interface/Trim zero padding to Trim date and time, now handles 2:00 pm > 2 pm * Fix trim zero of military time hour to not use 12 hr time * Change ThePirateBay to use oldpiratebay as a temporary fix +* Change Search Settings/Torrent/Deluge option texts for improved understanding [develop changelog] diff --git a/gui/slick/interfaces/default/config_search.tmpl b/gui/slick/interfaces/default/config_search.tmpl index 96fa4c25..9a4182ff 100755 --- a/gui/slick/interfaces/default/config_search.tmpl +++ b/gui/slick/interfaces/default/config_search.tmpl @@ -421,6 +421,7 @@ <div class="clear-left"> <p id="host_desc_torrent">URL to your torrent client (e.g. http://localhost:8000/)</p> <p id="host_desc_rtorrent" style="display:none"><b>Note:</b> <i>rTorrent</i> client URLs use e.g. scgi://localhost:5000/</p> + <p id="host_desc_deluge" style="display:none">URL to your Deluge WebUI (e.g. http://localhost:8112/)</p> </div> </span> </label> @@ -436,7 +437,7 @@ </label> </div> - <div class="field-pair"> + <div class="field-pair" id="torrent_username_option"> <label> <span class="component-title" id="username_title">Client username</span> <span class="component-desc"> diff --git a/gui/slick/js/configSearch.js b/gui/slick/js/configSearch.js index ecf7cccf..94c19931 100644 --- a/gui/slick/js/configSearch.js +++ b/gui/slick/js/configSearch.js @@ -62,7 +62,9 @@ $(document).ready(function(){ $(label_warning_deluge).hide(); $(host_desc_rtorrent).hide(); + $(host_desc_deluge).hide(); $(host_desc_torrent).show(); + $(torrent_username_option).show(); $(torrent_verify_cert_option).hide(); $(torrent_path_option).show(); $(torrent_path_option).find('.fileBrowser').show(); @@ -86,6 +88,9 @@ $(document).ready(function(){ client = 'Deluge'; $(torrent_verify_cert_option).show(); $(label_warning_deluge).show(); + $(host_desc_torrent).hide(); + $(host_desc_deluge).show(); + $(torrent_username_option).hide(); //$('#directory_title').text(client + directory); } else if ('download_station' == selectedProvider){ client = 'Synology DS'; From b2ca923270d05358d45d9e6356798c2bdc156f0c Mon Sep 17 00:00:00 2001 From: Supremicus <Supremicus@users.noreply.github.com> Date: Sun, 28 Dec 2014 01:14:40 +1000 Subject: [PATCH 07/21] Fix Womble's Index searching * Fix Womble's Index searching (ssl disabled for now, old categories are the new active ones again) --- CHANGES.md | 1 + sickbeard/providers/womble.py | 10 ++++------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 6be107da..307a212f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,6 +10,7 @@ * Fix trim zero of military time hour to not use 12 hr time * Change ThePirateBay to use oldpiratebay as a temporary fix * Change Search Settings/Torrent/Deluge option texts for improved understanding +* Fix Womble's Index searching (ssl disabled for now, old categories are the new active ones again) [develop changelog] diff --git a/sickbeard/providers/womble.py b/sickbeard/providers/womble.py index 81e639b4..0991eac3 100644 --- a/sickbeard/providers/womble.py +++ b/sickbeard/providers/womble.py @@ -30,7 +30,7 @@ class WombleProvider(generic.NZBProvider): generic.NZBProvider.__init__(self, "Womble's Index") self.enabled = False self.cache = WombleCache(self) - self.url = 'https://newshost.co.za/' + self.url = 'http://newshost.co.za/' def isEnabled(self): return self.enabled @@ -53,7 +53,7 @@ class WombleCache(tvcache.TVCache): return cl = [] - for url in [self.provider.url + 'rss/?sec=tv-sd&fr=false', self.provider.url + 'rss/?sec=tv-hd&fr=false']: + for url in [self.provider.url + 'rss/?sec=tv-x264&fr=false', self.provider.url + 'rss/?sec=tv-sd&fr=false', self.provider.url + 'rss/?sec=tv-hd&fr=false']: logger.log(u"Womble's Index cache update URL: " + url, logger.DEBUG) data = self.getRSSFeed(url) @@ -63,12 +63,11 @@ class WombleCache(tvcache.TVCache): # By now we know we've got data and no auth errors, all we need to do is put it in the database for item in data.entries: - ci = self._parseItem(item) + title, url = self._get_title_and_url(item) + ci = self._parseItem(title, url) if ci is not None: cl.append(ci) - - if len(cl) > 0: myDB = self._getDB() myDB.mass_action(cl) @@ -81,4 +80,3 @@ class WombleCache(tvcache.TVCache): return data != 'Invalid Link' provider = WombleProvider() - From 42e089dfa11bec40fd8281bc416792f325929a21 Mon Sep 17 00:00:00 2001 From: Prinz23 <Prinz2311@gmail.com> Date: Wed, 31 Dec 2014 18:25:52 +0100 Subject: [PATCH 08/21] Fix Add From Trending Show page to work with Trakt changes. ID changed from number. Poster URLs changed. --- CHANGES.md | 1 + gui/slick/interfaces/default/home_trendingShows.tmpl | 2 +- sickbeard/webserve.py | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 307a212f..6880d0cf 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,6 +11,7 @@ * Change ThePirateBay to use oldpiratebay as a temporary fix * Change Search Settings/Torrent/Deluge option texts for improved understanding * Fix Womble's Index searching (ssl disabled for now, old categories are the new active ones again) +* Fix Add From Trending Show page to work with Trakt changes [develop changelog] diff --git a/gui/slick/interfaces/default/home_trendingShows.tmpl b/gui/slick/interfaces/default/home_trendingShows.tmpl index 6bc04d26..3197db5b 100644 --- a/gui/slick/interfaces/default/home_trendingShows.tmpl +++ b/gui/slick/interfaces/default/home_trendingShows.tmpl @@ -129,7 +129,7 @@ #else #for $cur_show in $trending_shows: -#set $image = re.sub(r'(.*)(\..*?)$', r'\1-300\2', $cur_show['images']['poster'], 0, re.IGNORECASE | re.MULTILINE) +#set $image = re.sub(r'(.*)/original/(.+)$', r'\1/thumb/\2', $cur_show['images']['poster'], 0, re.IGNORECASE | re.MULTILINE) <div class="trakt_show <%= ('notinlibrary', 'inlibrary')[':' in cur_show['show_id']] %>" data-name="$cur_show['title']" data-rating="$cur_show['ratings']['percentage']" data-votes="$cur_show['ratings']['votes']"> <div class="traktContainer"> diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py index 9d888825..e51cded0 100644 --- a/sickbeard/webserve.py +++ b/sickbeard/webserve.py @@ -2980,7 +2980,7 @@ class NewHomeAddShows(MainHandler): tvdbs = ['tvdb_id', 'tvrage_id'] for index, tvdb in enumerate(tvdbs): try: - item[u'show_id'] = item[tvdb] + item[u'show_id'] = str(item[tvdb]) tvshow = helpers.findCertainShow(sickbeard.showList, int(item[tvdb])) except: continue From a1e8d21614e429a49a7bd5817c0a715eec3110d1 Mon Sep 17 00:00:00 2001 From: Adam <adam111316@users.noreply.github.com> Date: Tue, 16 Dec 2014 19:54:32 +0800 Subject: [PATCH 09/21] Fix name parser unit tests and regex Add anime unit test cases (port from lad1337/sickbeard) Fix normal tv show regex (port from midgetspy/sickbeard) Fix anime regex (port from lad1337/sickbeard) --- CHANGES.md | 7 + sickbeard/name_parser/parser.py | 446 ++++++++++++----------- sickbeard/name_parser/regexes.py | 428 +++++++++++----------- tests/name_parser_tests.py | 589 +++++++++++++++++++------------ 4 files changed, 806 insertions(+), 664 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 6880d0cf..09c4b64a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -12,6 +12,9 @@ * Change Search Settings/Torrent/Deluge option texts for improved understanding * Fix Womble's Index searching (ssl disabled for now, old categories are the new active ones again) * Fix Add From Trending Show page to work with Trakt changes +* Add anime unit test cases (port from lad1337/sickbeard) +* Fix normal tv show regex (port from midgetspy/sickbeard) +* Fix anime regex (port from lad1337/sickbeard) [develop changelog] @@ -56,6 +59,10 @@ * Fix restart issue * Fix to use new TorrentDay URLs * Fix typo in menu item Manage/Update XBMC +* Fix NameParser unittests +* Add Anime unittest cases (port from lad1337/sickbeard) +* Fix normal tv show regex (port from midgetspy/sickbeard) +* Fix anime regex (port from lad1337/sickbeard) ### 0.4.0 (2014-12-04 10:50:00 UTC) diff --git a/sickbeard/name_parser/parser.py b/sickbeard/name_parser/parser.py index 4bd77985..dc665ca0 100644 --- a/sickbeard/name_parser/parser.py +++ b/sickbeard/name_parser/parser.py @@ -26,8 +26,9 @@ import os.path import regexes import sickbeard -from sickbeard import logger, helpers, scene_numbering, common, exceptions, scene_exceptions, encodingKludge as ek, db +from sickbeard import logger, helpers, scene_numbering, common, scene_exceptions, encodingKludge as ek, db from dateutil import parser +from sickbeard.exceptions import ex class NameParser(object): @@ -36,13 +37,14 @@ class NameParser(object): ANIME_REGEX = 2 def __init__(self, file_name=True, showObj=None, tryIndexers=False, convert=False, - naming_pattern=False): + naming_pattern=False, testing=False): self.file_name = file_name self.showObj = showObj self.tryIndexers = tryIndexers self.convert = convert self.naming_pattern = naming_pattern + self.testing = testing if self.showObj and not self.showObj.is_anime: self._compile_regexes(self.NORMAL_REGEX) @@ -78,7 +80,7 @@ class NameParser(object): def _compile_regexes(self, regexMode): if regexMode == self.ANIME_REGEX: logger.log(u"Using ANIME regexs", logger.DEBUG) - uncompiled_regex = [regexes.anime_regexes, regexes.normal_regexes] + uncompiled_regex = [regexes.anime_regexes] elif regexMode == self.NORMAL_REGEX: logger.log(u"Using NORMAL regexs", logger.DEBUG) uncompiled_regex = [regexes.normal_regexes] @@ -86,7 +88,8 @@ class NameParser(object): logger.log(u"Using ALL regexes", logger.DEBUG) uncompiled_regex = [regexes.normal_regexes, regexes.anime_regexes] - self.compiled_regexes = [] + self.compiled_regexes = {0: [], 1: []} + index = 0 for regexItem in uncompiled_regex: for cur_pattern_num, (cur_pattern_name, cur_pattern) in enumerate(regexItem): try: @@ -94,7 +97,8 @@ class NameParser(object): except re.error, errormsg: logger.log(u"WARNING: Invalid episode_pattern, %s. %s" % (errormsg, cur_pattern)) else: - self.compiled_regexes.append((cur_pattern_num, cur_pattern_name, cur_regex)) + self.compiled_regexes[index].append([cur_pattern_num, cur_pattern_name, cur_regex]) + index += 1 def _parse_string(self, name): if not name: @@ -102,233 +106,242 @@ class NameParser(object): matches = [] bestResult = None + for regex in self.compiled_regexes: + for (cur_regex_num, cur_regex_name, cur_regex) in self.compiled_regexes[regex]: + match = cur_regex.match(name) - for (cur_regex_num, cur_regex_name, cur_regex) in self.compiled_regexes: - match = cur_regex.match(name) - - if not match: - continue - - result = ParseResult(name) - result.which_regex = [cur_regex_name] - result.score = 0 - cur_regex_num - - named_groups = match.groupdict().keys() - - if 'series_name' in named_groups: - result.series_name = match.group('series_name') - if result.series_name: - result.series_name = self.clean_series_name(result.series_name) - result.score += 1 - - if 'series_num' in named_groups and match.group('series_num'): - result.score += 1 - - if 'season_num' in named_groups: - tmp_season = int(match.group('season_num')) - if cur_regex_name == 'bare' and tmp_season in (19, 20): - continue - result.season_number = tmp_season - result.score += 1 - - if 'ep_num' in named_groups: - ep_num = self._convert_number(match.group('ep_num')) - if 'extra_ep_num' in named_groups and match.group('extra_ep_num'): - result.episode_numbers = range(ep_num, self._convert_number(match.group('extra_ep_num')) + 1) - result.score += 1 - else: - result.episode_numbers = [ep_num] - result.score += 1 - - if 'ep_ab_num' in named_groups: - ep_ab_num = self._convert_number(match.group('ep_ab_num')) - if 'extra_ab_ep_num' in named_groups and match.group('extra_ab_ep_num'): - result.ab_episode_numbers = range(ep_ab_num, - self._convert_number(match.group('extra_ab_ep_num')) + 1) - result.score += 1 - else: - result.ab_episode_numbers = [ep_ab_num] - result.score += 1 - - if 'air_date' in named_groups: - air_date = match.group('air_date') - try: - result.air_date = parser.parse(air_date, fuzzy=True).date() - result.score += 1 - except: + if not match: continue - if 'extra_info' in named_groups: - tmp_extra_info = match.group('extra_info') + result = ParseResult(name) + result.which_regex = [cur_regex_name] + result.score = 0 - cur_regex_num - # Show.S04.Special or Show.S05.Part.2.Extras is almost certainly not every episode in the season - if tmp_extra_info and cur_regex_name == 'season_only' and re.search( - r'([. _-]|^)(special|extra)s?\w*([. _-]|$)', tmp_extra_info, re.I): - continue - result.extra_info = tmp_extra_info - result.score += 1 + named_groups = match.groupdict().keys() - if 'release_group' in named_groups: - result.release_group = match.group('release_group') - result.score += 1 + if 'series_name' in named_groups: + result.series_name = match.group('series_name') + if result.series_name: + result.series_name = self.clean_series_name(result.series_name) + result.score += 1 - if 'version' in named_groups: - # assigns version to anime file if detected using anime regex. Non-anime regex receives -1 - version = match.group('version') - if version: - result.version = version - else: - result.version = 1 - else: - result.version = -1 + if 'series_num' in named_groups and match.group('series_num'): + result.score += 1 - matches.append(result) + if 'season_num' in named_groups: + tmp_season = int(match.group('season_num')) + if cur_regex_name == 'bare' and tmp_season in (19, 20): + continue + result.season_number = tmp_season + result.score += 1 - if len(matches): - # pick best match with highest score based on placement - bestResult = max(sorted(matches, reverse=True, key=lambda x: x.which_regex), key=lambda x: x.score) + if 'ep_num' in named_groups: + ep_num = self._convert_number(match.group('ep_num')) + if 'extra_ep_num' in named_groups and match.group('extra_ep_num'): + result.episode_numbers = range(ep_num, self._convert_number(match.group('extra_ep_num')) + 1) + result.score += 1 + else: + result.episode_numbers = [ep_num] + result.score += 1 - show = None - if not self.naming_pattern: - # try and create a show object for this result - show = helpers.get_show(bestResult.series_name, self.tryIndexers) + if 'ep_ab_num' in named_groups: + ep_ab_num = self._convert_number(match.group('ep_ab_num')) + if 'extra_ab_ep_num' in named_groups and match.group('extra_ab_ep_num'): + result.ab_episode_numbers = range(ep_ab_num, + self._convert_number(match.group('extra_ab_ep_num')) + 1) + result.score += 1 + else: + result.ab_episode_numbers = [ep_ab_num] + result.score += 1 - # confirm passed in show object indexer id matches result show object indexer id - if show: - if self.showObj and show.indexerid != self.showObj.indexerid: - show = None - bestResult.show = show - elif not show and self.showObj: - bestResult.show = self.showObj - - # if this is a naming pattern test or result doesn't have a show object then return best result - if not bestResult.show or self.naming_pattern: - return bestResult - - # get quality - bestResult.quality = common.Quality.nameQuality(name, bestResult.show.is_anime) - - new_episode_numbers = [] - new_season_numbers = [] - new_absolute_numbers = [] - - # if we have an air-by-date show then get the real season/episode numbers - if bestResult.is_air_by_date: - airdate = bestResult.air_date.toordinal() - myDB = db.DBConnection() - sql_result = myDB.select( - "SELECT season, episode FROM tv_episodes WHERE showid = ? and indexer = ? and airdate = ?", - [bestResult.show.indexerid, bestResult.show.indexer, airdate]) - - season_number = None - episode_numbers = [] - - if sql_result: - season_number = int(sql_result[0][0]) - episode_numbers = [int(sql_result[0][1])] - - if not season_number or not len(episode_numbers): + if 'air_year' in named_groups and 'air_month' in named_groups and 'air_day' in named_groups: + year = int(match.group('air_year')) + month = int(match.group('air_month')) + day = int(match.group('air_day')) + # make an attempt to detect YYYY-DD-MM formats + if month > 12: + tmp_month = month + month = day + day = tmp_month try: - lINDEXER_API_PARMS = sickbeard.indexerApi(bestResult.show.indexer).api_params.copy() + result.air_date = datetime.date(year, month, day) + except ValueError, e: + raise InvalidNameException(ex(e)) - if bestResult.show.lang: - lINDEXER_API_PARMS['language'] = bestResult.show.lang + if 'extra_info' in named_groups: + tmp_extra_info = match.group('extra_info') - t = sickbeard.indexerApi(bestResult.show.indexer).indexer(**lINDEXER_API_PARMS) + # Show.S04.Special or Show.S05.Part.2.Extras is almost certainly not every episode in the season + if tmp_extra_info and cur_regex_name == 'season_only' and re.search( + r'([. _-]|^)(special|extra)s?\w*([. _-]|$)', tmp_extra_info, re.I): + continue + result.extra_info = tmp_extra_info + result.score += 1 - epObj = t[bestResult.show.indexerid].airedOn(bestResult.air_date)[0] + if 'release_group' in named_groups: + result.release_group = match.group('release_group') + result.score += 1 - season_number = int(epObj["seasonnumber"]) - episode_numbers = [int(epObj["episodenumber"])] - except sickbeard.indexer_episodenotfound: - logger.log(u"Unable to find episode with date " + str(bestResult.air_date) + " for show " + bestResult.show.name + ", skipping", logger.WARNING) - episode_numbers = [] - except sickbeard.indexer_error, e: - logger.log(u"Unable to contact " + sickbeard.indexerApi(bestResult.show.indexer).name + ": " + ex(e), logger.WARNING) - episode_numbers = [] + if 'version' in named_groups: + # assigns version to anime file if detected using anime regex. Non-anime regex receives -1 + version = match.group('version') + if version: + result.version = version + else: + result.version = 1 + else: + result.version = -1 - for epNo in episode_numbers: - s = season_number - e = epNo + matches.append(result) - if self.convert: - (s, e) = scene_numbering.get_indexer_numbering(bestResult.show.indexerid, - bestResult.show.indexer, - season_number, - epNo) - new_episode_numbers.append(e) - new_season_numbers.append(s) + if len(matches): + # pick best match with highest score based on placement + bestResult = max(sorted(matches, reverse=True, key=lambda x: x.which_regex), key=lambda x: x.score) - elif bestResult.show.is_anime and len(bestResult.ab_episode_numbers): - scene_season = scene_exceptions.get_scene_exception_by_name(bestResult.series_name)[1] - for epAbsNo in bestResult.ab_episode_numbers: - a = epAbsNo + show = None + if not self.naming_pattern: + # try and create a show object for this result + show = helpers.get_show(bestResult.series_name, self.tryIndexers) - if self.convert: - a = scene_numbering.get_indexer_absolute_numbering(bestResult.show.indexerid, - bestResult.show.indexer, epAbsNo, - True, scene_season) + # confirm passed in show object indexer id matches result show object indexer id + if show and not self.testing: + if self.showObj and show.indexerid != self.showObj.indexerid: + show = None + bestResult.show = show + elif not show and self.showObj: + bestResult.show = self.showObj - (s, e) = helpers.get_all_episodes_from_absolute_number(bestResult.show, [a]) + if bestResult.show and bestResult.show.is_anime and len(self.compiled_regexes[1]) > 1 and regex != 1: + continue - new_absolute_numbers.append(a) - new_episode_numbers.extend(e) - new_season_numbers.append(s) + # if this is a naming pattern test or result doesn't have a show object then return best result + if not bestResult.show or self.naming_pattern: + return bestResult - elif bestResult.season_number and len(bestResult.episode_numbers): - for epNo in bestResult.episode_numbers: - s = bestResult.season_number - e = epNo + # get quality + bestResult.quality = common.Quality.nameQuality(name, bestResult.show.is_anime) - if self.convert: - (s, e) = scene_numbering.get_indexer_numbering(bestResult.show.indexerid, - bestResult.show.indexer, - bestResult.season_number, - epNo) - if bestResult.show.is_anime: - a = helpers.get_absolute_number_from_season_and_episode(bestResult.show, s, e) - if a: - new_absolute_numbers.append(a) + new_episode_numbers = [] + new_season_numbers = [] + new_absolute_numbers = [] - new_episode_numbers.append(e) - new_season_numbers.append(s) + # if we have an air-by-date show then get the real season/episode numbers + if bestResult.is_air_by_date: + airdate = bestResult.air_date.toordinal() + myDB = db.DBConnection() + sql_result = myDB.select( + "SELECT season, episode FROM tv_episodes WHERE showid = ? and indexer = ? and airdate = ?", + [bestResult.show.indexerid, bestResult.show.indexer, airdate]) - # need to do a quick sanity check heregex. It's possible that we now have episodes - # from more than one season (by tvdb numbering), and this is just too much - # for sickbeard, so we'd need to flag it. - new_season_numbers = list(set(new_season_numbers)) # remove duplicates - if len(new_season_numbers) > 1: - raise InvalidNameException("Scene numbering results episodes from " - "seasons %s, (i.e. more than one) and " - "SickGear does not support this. " - "Sorry." % (str(new_season_numbers))) + season_number = None + episode_numbers = [] - # I guess it's possible that we'd have duplicate episodes too, so lets - # eliminate them - new_episode_numbers = list(set(new_episode_numbers)) - new_episode_numbers.sort() + if sql_result: + season_number = int(sql_result[0][0]) + episode_numbers = [int(sql_result[0][1])] - # maybe even duplicate absolute numbers so why not do them as well - new_absolute_numbers = list(set(new_absolute_numbers)) - new_absolute_numbers.sort() + if not season_number or not len(episode_numbers): + try: + lINDEXER_API_PARMS = sickbeard.indexerApi(bestResult.show.indexer).api_params.copy() - if len(new_absolute_numbers): - bestResult.ab_episode_numbers = new_absolute_numbers + if bestResult.show.lang: + lINDEXER_API_PARMS['language'] = bestResult.show.lang - if len(new_season_numbers) and len(new_episode_numbers): - bestResult.episode_numbers = new_episode_numbers - bestResult.season_number = new_season_numbers[0] + t = sickbeard.indexerApi(bestResult.show.indexer).indexer(**lINDEXER_API_PARMS) - if self.convert: - logger.log( - u"Converted parsed result " + bestResult.original_name + " into " + str(bestResult).decode('utf-8', - 'xmlcharrefreplace'), - logger.DEBUG) + epObj = t[bestResult.show.indexerid].airedOn(bestResult.air_date)[0] - # CPU sleep - time.sleep(0.02) + season_number = int(epObj["seasonnumber"]) + episode_numbers = [int(epObj["episodenumber"])] + except sickbeard.indexer_episodenotfound: + logger.log(u"Unable to find episode with date " + str(bestResult.air_date) + " for show " + bestResult.show.name + ", skipping", logger.WARNING) + episode_numbers = [] + except sickbeard.indexer_error, e: + logger.log(u"Unable to contact " + sickbeard.indexerApi(bestResult.show.indexer).name + ": " + ex(e), logger.WARNING) + episode_numbers = [] - return bestResult + for epNo in episode_numbers: + s = season_number + e = epNo + + if self.convert: + (s, e) = scene_numbering.get_indexer_numbering(bestResult.show.indexerid, + bestResult.show.indexer, + season_number, + epNo) + new_episode_numbers.append(e) + new_season_numbers.append(s) + + elif bestResult.show.is_anime and len(bestResult.ab_episode_numbers) and not self.testing: + scene_season = scene_exceptions.get_scene_exception_by_name(bestResult.series_name)[1] + for epAbsNo in bestResult.ab_episode_numbers: + a = epAbsNo + + if self.convert: + a = scene_numbering.get_indexer_absolute_numbering(bestResult.show.indexerid, + bestResult.show.indexer, epAbsNo, + True, scene_season) + + (s, e) = helpers.get_all_episodes_from_absolute_number(bestResult.show, [a]) + + new_absolute_numbers.append(a) + new_episode_numbers.extend(e) + new_season_numbers.append(s) + + elif bestResult.season_number and len(bestResult.episode_numbers) and not self.testing: + for epNo in bestResult.episode_numbers: + s = bestResult.season_number + e = epNo + + if self.convert: + (s, e) = scene_numbering.get_indexer_numbering(bestResult.show.indexerid, + bestResult.show.indexer, + bestResult.season_number, + epNo) + if bestResult.show.is_anime: + a = helpers.get_absolute_number_from_season_and_episode(bestResult.show, s, e) + if a: + new_absolute_numbers.append(a) + + new_episode_numbers.append(e) + new_season_numbers.append(s) + + # need to do a quick sanity check heregex. It's possible that we now have episodes + # from more than one season (by tvdb numbering), and this is just too much + # for sickbeard, so we'd need to flag it. + new_season_numbers = list(set(new_season_numbers)) # remove duplicates + if len(new_season_numbers) > 1: + raise InvalidNameException("Scene numbering results episodes from " + "seasons %s, (i.e. more than one) and " + "SickGear does not support this. " + "Sorry." % (str(new_season_numbers))) + + # I guess it's possible that we'd have duplicate episodes too, so lets + # eliminate them + new_episode_numbers = list(set(new_episode_numbers)) + new_episode_numbers.sort() + + # maybe even duplicate absolute numbers so why not do them as well + new_absolute_numbers = list(set(new_absolute_numbers)) + new_absolute_numbers.sort() + + if len(new_absolute_numbers): + bestResult.ab_episode_numbers = new_absolute_numbers + + if len(new_season_numbers) and len(new_episode_numbers): + bestResult.episode_numbers = new_episode_numbers + bestResult.season_number = new_season_numbers[0] + + if self.convert: + logger.log( + u"Converted parsed result " + bestResult.original_name + " into " + str(bestResult).decode('utf-8', + 'xmlcharrefreplace'), + logger.DEBUG) + + # CPU sleep + time.sleep(0.02) + + return bestResult def _combine_results(self, first, second, attr): # if the first doesn't exist then return the second or nothing @@ -416,7 +429,7 @@ class NameParser(object): file_name_result = self._parse_string(base_file_name) # use only the direct parent dir - dir_name = os.path.basename(dir_name) + dir_name = ek.ek(os.path.basename, dir_name) # parse the dirname for extra info if needed dir_name_result = self._parse_string(dir_name) @@ -452,8 +465,12 @@ class NameParser(object): final_result.quality = self._combine_results(file_name_result, dir_name_result, 'quality') if not final_result.show: - raise InvalidShowException( - "Unable to parse " + name.encode(sickbeard.SYS_ENCODING, 'xmlcharrefreplace')) + if self.testing: + pass + #final_result.which_regex = [] + else: + raise InvalidShowException( + "Unable to parse " + name.encode(sickbeard.SYS_ENCODING, 'xmlcharrefreplace')) # if there's no useful info in it then raise an exception if final_result.season_number == None and not final_result.episode_numbers and final_result.air_date == None and not final_result.ab_episode_numbers and not final_result.series_name: @@ -506,7 +523,7 @@ class ParseResult(object): self.air_date = air_date - self.which_regex = [] + self.which_regex = None self.show = show self.score = score @@ -530,14 +547,14 @@ class ParseResult(object): return False if self.ab_episode_numbers != other.ab_episode_numbers: return False - if self.show != other.show: - return False - if self.score != other.score: - return False - if self.quality != other.quality: - return False - if self.version != other.version: - return False + #if self.show != other.show: + # return False + #if self.score != other.score: + # return False + #if self.quality != other.quality: + # return False + #if self.version != other.version: + # return False return True @@ -556,8 +573,9 @@ class ParseResult(object): to_return += str(self.air_date) if self.ab_episode_numbers: to_return += ' [ABS: ' + str(self.ab_episode_numbers) + ']' - if self.version: - to_return += ' [ANIME VER: ' + str(self.version) + ']' + if self.is_anime: + if self.version: + to_return += ' [ANIME VER: ' + str(self.version) + ']' if self.release_group: to_return += ' [GROUP: ' + self.release_group + ']' diff --git a/sickbeard/name_parser/regexes.py b/sickbeard/name_parser/regexes.py index f3e15cb6..b9b58d30 100644 --- a/sickbeard/name_parser/regexes.py +++ b/sickbeard/name_parser/regexes.py @@ -23,29 +23,31 @@ normal_regexes = [ # Show.Name.S01E02.S01E03.Source.Quality.Etc-Group # Show Name - S01E02 - S01E03 - S01E04 - Ep Name ''' - ^(?P<series_name>.+?)[. _-]+ # Show_Name and separator - s(?P<season_num>\d+)[. _-]* # S01 and optional separator - e(?P<ep_num>\d+) # E02 and separator - ([. _-]+s(?P=season_num)[. _-]* # S01 and optional separator - e(?P<extra_ep_num>\d+))+ # E03/etc and separator - [. _-]*((?P<extra_info>.+?) # Source_Quality_Etc- - ((?<![. _-])(?<!WEB) # Make sure this is really the release group - -(?P<release_group>[^- ]+([. _-]\[.*\])?))?)?$ # Group - '''), + ^(?P<series_name>.+?)[. _-]+ # Show_Name and separator + s(?P<season_num>\d+)[. _-]* # S01 and optional separator + e(?P<ep_num>\d+) # E02 and separator + ([. _-]+s(?P=season_num)[. _-]* # S01 and optional separator + e(?P<extra_ep_num>\d+))+ # E03/etc and separator + [. _-]*((?P<extra_info>.+?) # Source_Quality_Etc- + ((?<![. _-])(?<!WEB) # Make sure this is really the release group + -(?P<release_group>[^- ]+))?)?$ # Group + ''' + ), ('fov_repeat', # Show.Name.1x02.1x03.Source.Quality.Etc-Group # Show Name - 1x02 - 1x03 - 1x04 - Ep Name ''' - ^(?P<series_name>.+?)[. _-]+ # Show_Name and separator - (?P<season_num>\d+)x # 1x - (?P<ep_num>\d+) # 02 and separator - ([. _-]+(?P=season_num)x # 1x - (?P<extra_ep_num>\d+))+ # 03/etc and separator - [. _-]*((?P<extra_info>.+?) # Source_Quality_Etc- - ((?<![. _-])(?<!WEB) # Make sure this is really the release group - -(?P<release_group>[^- ]+([. _-]\[.*\])?))?)?$ # Group - '''), + ^(?P<series_name>.+?)[. _-]+ # Show_Name and separator + (?P<season_num>\d+)x # 1x + (?P<ep_num>\d+) # 02 and separator + ([. _-]+(?P=season_num)x # 1x + (?P<extra_ep_num>\d+))+ # 03/etc and separator + [. _-]*((?P<extra_info>.+?) # Source_Quality_Etc- + ((?<![. _-])(?<!WEB) # Make sure this is really the release group + -(?P<release_group>[^- ]+))?)?$ # Group + ''' + ), ('standard', # Show.Name.S01E02.Source.Quality.Etc-Group @@ -55,15 +57,16 @@ normal_regexes = [ # Show Name - S01E02-03 - My Ep Name # Show.Name.S01.E02.E03 ''' - ^((?P<series_name>.+?)[. _-]+)? # Show_Name and separator - s(?P<season_num>\d+)[. _-]* # S01 and optional separator - e(?P<ep_num>\d+) # E02 and separator - (([. _-]*e|-) # linking e/- char - (?P<extra_ep_num>(?!(1080|720|480)[pi])\d+))* # additional E03/etc - [. _-]*((?P<extra_info>.+?) # Source_Quality_Etc- - ((?<![. _-])(?<!WEB) # Make sure this is really the release group - -(?P<release_group>[^- ]+([. _-]\[.*\])?))?)?$ # Group - '''), + ^((?P<series_name>.+?)[. _-]+)? # Show_Name and separator + s(?P<season_num>\d+)[. _-]* # S01 and optional separator + e(?P<ep_num>\d+) # E02 and separator + (([. _-]*e|-) # linking e/- char + (?P<extra_ep_num>(?!(1080|720|480)[pi])\d+))* # additional E03/etc + [. _-]*((?P<extra_info>.+?) # Source_Quality_Etc- + ((?<![. _-])(?<!WEB) # Make sure this is really the release group + -(?P<release_group>[^- ]+))?)?$ # Group + ''' + ), ('fov', # Show_Name.1x02.Source_Quality_Etc-Group @@ -71,70 +74,64 @@ normal_regexes = [ # Show_Name.1x02x03x04.Source_Quality_Etc-Group # Show Name - 1x02-03-04 - My Ep Name ''' - ^((?P<series_name>.+?)[\[. _-]+)? # Show_Name and separator - (?P<season_num>\d+)x # 1x - (?P<ep_num>\d+) # 02 and separator - (([. _-]*x|-) # linking x/- char + ^((?P<series_name>.+?)[\[. _-]+)? # Show_Name and separator + (?P<season_num>\d+)x # 1x + (?P<ep_num>\d+) # 02 and separator + (([. _-]*x|-) # linking x/- char (?P<extra_ep_num> - (?!(1080|720|480)[pi])(?!(?<=x)264) # ignore obviously wrong multi-eps - \d+))* # additional x03/etc - [\]. _-]*((?P<extra_info>.+?) # Source_Quality_Etc- - ((?<![. _-])(?<!WEB) # Make sure this is really the release group - -(?P<release_group>[^- ]+([. _-]\[.*\])?))?)?$ # Group - '''), + (?!(1080|720|480)[pi])(?!(?<=x)264) # ignore obviously wrong multi-eps + \d+))* # additional x03/etc + [\]. _-]*((?P<extra_info>.+?) # Source_Quality_Etc- + ((?<![. _-])(?<!WEB) # Make sure this is really the release group + -(?P<release_group>[^- ]+))?)?$ # Group + ''' + ), ('scene_date_format', # Show.Name.2010.11.23.Source.Quality.Etc-Group # Show Name - 2010-11-23 - Ep Name ''' - ^((?P<series_name>.+?)[. _-]+)? # Show_Name and separator - (?P<air_date>(\d+[. _-]\d+[. _-]\d+)|(\d+\w+[. _-]\w+[. _-]\d+)) - [. _-]*((?P<extra_info>.+?) # Source_Quality_Etc- - ((?<![. _-])(?<!WEB) # Make sure this is really the release group - -(?P<release_group>[^- ]+([. _-]\[.*\])?))?)?$ # Group - '''), - - ('scene_sports_format', - # Show.Name.100.Event.2010.11.23.Source.Quality.Etc-Group - # Show.Name.2010.11.23.Source.Quality.Etc-Group - # Show Name - 2010-11-23 - Ep Name + ^((?P<series_name>.+?)[. _-]+)? # Show_Name and separator + (?P<air_year>\d{4})[. _-]+ # 2010 and separator + (?P<air_month>\d{2})[. _-]+ # 11 and separator + (?P<air_day>\d{2}) # 23 and separator + [. _-]*((?P<extra_info>.+?) # Source_Quality_Etc- + ((?<![. _-])(?<!WEB) # Make sure this is really the release group + -(?P<release_group>[^- ]+))?)?$ # Group ''' - ^(?P<series_name>.*?(UEFA|MLB|ESPN|WWE|MMA|UFC|TNA|EPL|NASCAR|NBA|NFL|NHL|NRL|PGA|SUPER LEAGUE|FORMULA|FIFA|NETBALL|MOTOGP).*?)[. _-]+ - ((?P<series_num>\d{1,3})[. _-]+)? - (?P<air_date>(\d+[. _-]\d+[. _-]\d+)|(\d+\w+[. _-]\w+[. _-]\d+))[. _-]+ - ((?P<extra_info>.+?)((?<![. _-]) - (?<!WEB)-(?P<release_group>[^- ]+([. _-]\[.*\])?))?)?$ - '''), + ), ('stupid', # tpz-abc102 ''' - (?P<release_group>.+?)-\w+?[\. ]? # tpz-abc - (?!264) # don't count x264 - (?P<season_num>\d{1,2}) # 1 - (?P<ep_num>\d{2})$ # 02 - '''), + (?P<release_group>.+?)-\w+?[\. ]? # tpz-abc + (?!264) # don't count x264 + (?P<season_num>\d{1,2}) # 1 + (?P<ep_num>\d{2})$ # 02 + ''' + ), ('verbose', # Show Name Season 1 Episode 2 Ep Name ''' - ^(?P<series_name>.+?)[. _-]+ # Show Name and separator - season[. _-]+ # season and separator - (?P<season_num>\d+)[. _-]+ # 1 - episode[. _-]+ # episode and separator - (?P<ep_num>\d+)[. _-]+ # 02 and separator - (?P<extra_info>.+)$ # Source_Quality_Etc- - '''), + ^(?P<series_name>.+?)[. _-]+ # Show Name and separator + season[. _-]+ # season and separator + (?P<season_num>\d+)[. _-]+ # 1 + episode[. _-]+ # episode and separator + (?P<ep_num>\d+)[. _-]+ # 02 and separator + (?P<extra_info>.+)$ # Source_Quality_Etc- + ''' + ), ('season_only', # Show.Name.S01.Source.Quality.Etc-Group ''' - ^((?P<series_name>.+?)[. _-]+)? # Show_Name and separator - s(eason[. _-])? # S01/Season 01 - (?P<season_num>\d+)[. _-]* # S01 and optional separator - [. _-]*((?P<extra_info>.+?) # Source_Quality_Etc- - ((?<![. _-])(?<!WEB) # Make sure this is really the release group - -(?P<release_group>[^- ]+([. _-]\[.*\])?))?)?$ # Group + ^((?P<series_name>.+?)[. _-]+)? # Show_Name and separator + s(eason[. _-])? # S01/Season 01 + (?P<season_num>\d+)[. _-]* # S01 and optional separator + [. _-]*((?P<extra_info>.+?) # Source_Quality_Etc- + ((?<![. _-])(?<!WEB) # Make sure this is really the release group + -(?P<release_group>[^- ]+))?)?$ # Group ''' ), @@ -142,14 +139,14 @@ normal_regexes = [ # Show.Name.E02-03 # Show.Name.E02.2010 ''' - ^((?P<series_name>.+?)[. _-]+)? # Show_Name and separator - (e(p(isode)?)?|part|pt)[. _-]? # e, ep, episode, or part - (?P<ep_num>(\d+|[ivx]+)) # first ep num - ((([. _-]+(and|&|to)[. _-]+)|-) # and/&/to joiner + ^((?P<series_name>.+?)[. _-]+)? # Show_Name and separator + (e(p(isode)?)?|part|pt)[. _-]? # e, ep, episode, or part + (?P<ep_num>(\d+|[ivx]+)) # first ep num + ((([. _-]+(and|&|to)[. _-]+)|-) # and/&/to joiner (?P<extra_ep_num>(?!(1080|720|480)[pi])(\d+|[ivx]+))[. _-]) # second ep num - ([. _-]*(?P<extra_info>.+?) # Source_Quality_Etc- - ((?<![. _-])(?<!WEB) # Make sure this is really the release group - -(?P<release_group>[^- ]+([. _-]\[.*\])?))?)?$ # Group + ([. _-]*(?P<extra_info>.+?) # Source_Quality_Etc- + ((?<![. _-])(?<!WEB) # Make sure this is really the release group + -(?P<release_group>[^- ]+))?)?$ # Group ''' ), @@ -158,58 +155,57 @@ normal_regexes = [ # Show.Name.Part.3.Source.Quality.Etc-Group # Show.Name.Part.1.and.Part.2.Blah-Group ''' - ^((?P<series_name>.+?)[. _-]+)? # Show_Name and separator - (e(p(isode)?)?|part|pt)[. _-]? # e, ep, episode, or part - (?P<ep_num>(\d+|([ivx]+(?=[. _-])))) # first ep num - ([. _-]+((and|&|to)[. _-]+)? # and/&/to joiner - ((e(p(isode)?)?|part|pt)[. _-]?) # e, ep, episode, or part + ^((?P<series_name>.+?)[. _-]+)? # Show_Name and separator + (e(p(isode)?)?|part|pt)[. _-]? # e, ep, episode, or part + (?P<ep_num>(\d+|([ivx]+(?=[. _-])))) # first ep num + ([. _-]+((and|&|to)[. _-]+)? # and/&/to joiner + ((e(p(isode)?)?|part|pt)[. _-]?) # e, ep, episode, or part (?P<extra_ep_num>(?!(1080|720|480)[pi]) - (\d+|([ivx]+(?=[. _-]))))[. _-])* # second ep num - ([. _-]*(?P<extra_info>.+?) # Source_Quality_Etc- - ((?<![. _-])(?<!WEB) # Make sure this is really the release group - -(?P<release_group>[^- ]+([. _-]\[.*\])?))?)?$ # Group - ''' - ), - - ('no_season', - # Show Name - 01 - Ep Name - # 01 - Ep Name - # 01 - Ep Name - ''' - ^((?P<series_name>.+?)(?:[. _-]{2,}|[. _]))? # Show_Name and separator - (?P<ep_num>\d{1,3}) # 02 - (?:-(?P<extra_ep_num>\d{1,3}))* # -03-04-05 etc - \s?of?\s?\d{1,3}? # of joiner (with or without spaces) and series total ep - [. _-]+((?P<extra_info>.+?) # Source_Quality_Etc- - ((?<![. _-])(?<!WEB) # Make sure this is really the release group - -(?P<release_group>[^- ]+([. _-]\[.*\])?))?)?$ # Group + (\d+|([ivx]+(?=[. _-]))))[. _-])* # second ep num + ([. _-]*(?P<extra_info>.+?) # Source_Quality_Etc- + ((?<![. _-])(?<!WEB) # Make sure this is really the release group + -(?P<release_group>[^- ]+))?)?$ # Group ''' ), ('bare', # Show.Name.102.Source.Quality.Etc-Group ''' - ^(?P<series_name>.+?)[. _-]+ # Show_Name and separator - (?P<season_num>\d{1,2}) # 1 - (?P<ep_num>\d{2}) # 02 and separator + ^(?P<series_name>.+?)[. _-]+ # Show_Name and separator + (?P<season_num>\d{1,2}) # 1 + (?P<ep_num>\d{2}) # 02 and separator ([. _-]+(?P<extra_info>(?!\d{3}[. _-]+)[^-]+) # Source_Quality_Etc- - (-(?P<release_group>[^- ]+([. _-]\[.*\])?))?)?$ # Group - '''), + (-(?P<release_group>.+))?)?$ # Group + ''' + ), + + ('no_season', + # Show Name - 01 - Ep Name + # 01 - Ep Name + ''' + ^((?P<series_name>.+?)(?:[. _-]{2,}|[. _]))? # Show_Name and separator + (?P<ep_num>\d{1,2}) # 01 + (?:-(?P<extra_ep_num>\d{1,2}))* # 02 + [. _-]+((?P<extra_info>.+?) # Source_Quality_Etc- + ((?<![. _-])(?<!WEB) # Make sure this is really the release group + -(?P<release_group>[^- ]+))?)?$ # Group + ''' + ), ] anime_regexes = [ ('anime_ultimate', - """ + ''' ^(?:\[(?P<release_group>.+?)\][ ._-]*) (?P<series_name>.+?)[ ._-]+ - (?P<ep_ab_num>((?!(1080|720|480)[pi])|(?![hx].?264))\d{1,3}) - (-(?P<extra_ab_ep_num>((?!(1080|720|480)[pi])|(?![hx].?264))\d{1,3}))?[ ._-]+? + (?P<ep_ab_num>\d{1,3}) + (-(?P<extra_ab_ep_num>\d{1,3}))?[ ._-]+? (?:v(?P<version>[0-9]))? (?:[\w\.]*) (?:(?:(?:[\[\(])(?P<extra_info>\d{3,4}[xp]?\d{0,4}[\.\w\s-]*)(?:[\]\)]))|(?:\d{3,4}[xp])) (?:[ ._]?\[(?P<crc>\w+)\])? .*? - """ + ''' ), ('anime_standard', # [Group Name] Show Name.13-14 @@ -219,163 +215,163 @@ anime_regexes = [ # [Group Name] Show Name - 13 # Show Name 13 ''' - ^(\[(?P<release_group>.+?)\][ ._-]*)? # Release Group and separator - (?P<series_name>.+?)[ ._-]+ # Show_Name and separator - (?P<ep_ab_num>((?!(1080|720|480)[pi])|(?![hx].?264))\d{1,3}) # E01 - (-(?P<extra_ab_ep_num>((?!(1080|720|480)[pi])|(?![hx].?264))\d{1,3}))? # E02 - (v(?P<version>[0-9]))? # version - [ ._-]+\[(?P<extra_info>\d{3,4}[xp]?\d{0,4}[\.\w\s-]*)\] # Source_Quality_Etc- - (\[(?P<crc>\w{8})\])? # CRC - .*? # Separator and EOL + ^(\[(?P<release_group>.+?)\][ ._-]*)? # Release Group and separator + (?P<series_name>.+?)[ ._-]+ # Show_Name and separator + (?P<ep_ab_num>\d{1,3}) # E01 + (-(?P<extra_ab_ep_num>\d{1,3}))? # E02 + (v(?P<version>[0-9]))? # version + [ ._-]+\[(?P<extra_info>\d{3,4}[xp]?\d{0,4}[\.\w\s-]*)\] # Source_Quality_Etc- + (\[(?P<crc>\w{8})\])? # CRC + .*? # Separator and EOL '''), - ('anime_standard_round', - # TODO examples # [Stratos-Subs]_Infinite_Stratos_-_12_(1280x720_H.264_AAC)_[379759DB] # [ShinBunBu-Subs] Bleach - 02-03 (CX 1280x720 x264 AAC) ''' - ^(\[(?P<release_group>.+?)\][ ._-]*)? # Release Group and separator - (?P<series_name>.+?)[ ._-]+ # Show_Name and separator - (?P<ep_ab_num>((?!(1080|720|480)[pi])|(?![hx].?264))\d{1,3}) # E01 - (-(?P<extra_ab_ep_num>((?!(1080|720|480)[pi])|(?![hx].?264))\d{1,3}))? # E02 - (v(?P<version>[0-9]))? # version - [ ._-]+\((?P<extra_info>(CX[ ._-]?)?\d{3,4}[xp]?\d{0,4}[\.\w\s-]*)\) # Source_Quality_Etc- - (\[(?P<crc>\w{8})\])? # CRC - .*? # Separator and EOL + ^(\[(?P<release_group>.+?)\][ ._-]*)? # Release Group and separator + (?P<series_name>.+?)[ ._-]+ # Show_Name and separator + (?P<ep_ab_num>\d{1,3}) # E01 + (-(?P<extra_ab_ep_num>\d{1,3}))? # E02 + (v(?P<version>[0-9]))? # version + [ ._-]+\((?P<extra_info>(CX[ ._-]?)?\d{3,4}[xp]?\d{0,4}[\.\w\s-]*)\) # Source_Quality_Etc- + (\[(?P<crc>\w{8})\])? # CRC + .*? # Separator and EOL '''), - ('anime_slash', # [SGKK] Bleach 312v1 [720p/MKV] ''' - ^(\[(?P<release_group>.+?)\][ ._-]*)? # Release Group and separator - (?P<series_name>.+?)[ ._-]+ # Show_Name and separator - (?P<ep_ab_num>((?!(1080|720|480)[pi])|(?![hx].?264))\d{1,3}) # E01 - (-(?P<extra_ab_ep_num>((?!(1080|720|480)[pi])|(?![hx].?264))\d{1,3}))? # E02 - (v(?P<version>[0-9]))? # version - [ ._-]+\[(?P<extra_info>\d{3,4}p) # Source_Quality_Etc- - (\[(?P<crc>\w{8})\])? # CRC - .*? # Separator and EOL + ^(\[(?P<release_group>.+?)\][ ._-]*)? # Release Group and separator + (?P<series_name>.+?)[ ._-]+ # Show_Name and separator + (?P<ep_ab_num>\d{1,3}) # E01 + (-(?P<extra_ab_ep_num>\d{1,3}))? # E02 + (v(?P<version>[0-9]))? # version + [ ._-]+\[(?P<extra_info>\d{3,4}p) # Source_Quality_Etc- + (\[(?P<crc>\w{8})\])? # CRC + .*? # Separator and EOL '''), - ('anime_standard_codec', # [Ayako]_Infinite_Stratos_-_IS_-_07_[H264][720p][EB7838FC] # [Ayako] Infinite Stratos - IS - 07v2 [H264][720p][44419534] # [Ayako-Shikkaku] Oniichan no Koto Nanka Zenzen Suki Janain Dakara ne - 10 [LQ][h264][720p] [8853B21C] ''' - ^(\[(?P<release_group>.+?)\][ ._-]*)? # Release Group and separator - (?P<series_name>.+?)[ ._]* # Show_Name and separator - ([ ._-]+-[ ._-]+[A-Z]+[ ._-]+)?[ ._-]+ # funny stuff, this is sooo nuts ! this will kick me in the butt one day - (?P<ep_ab_num>((?!(1080|720|480)[pi])|(?![hx].?264))\d{1,3}) # E01 - (-(?P<extra_ab_ep_num>((?!(1080|720|480)[pi])|(?![hx].?264))\d{1,3}))? # E02 - (v(?P<version>[0-9]))? # version - ([ ._-](\[\w{1,2}\])?\[[a-z][.]?\w{2,4}\])? #codec - [ ._-]*\[(?P<extra_info>(\d{3,4}[xp]?\d{0,4})?[\.\w\s-]*)\] # Source_Quality_Etc- - (\[(?P<crc>\w{8})\])? - .*? # Separator and EOL + ^(\[(?P<release_group>.+?)\][ ._-]*)? # Release Group and separator + (?P<series_name>.+?)[ ._]* # Show_Name and separator + ([ ._-]+-[ ._-]+[A-Z]+[ ._-]+)?[ ._-]+ # this will kick me in the butt one day + (?P<ep_ab_num>\d{1,3}) # E01 + (-(?P<extra_ab_ep_num>\d{1,3}))? # E02 + (v(?P<version>[0-9]))? # version + ([ ._-](\[\w{1,2}\])?\[[a-z][.]?\w{2,4}\])? # codec + [ ._-]*\[(?P<extra_info>(\d{3,4}[xp]?\d{0,4})?[\.\w\s-]*)\] # Source_Quality_Etc- + (\[(?P<crc>\w{8})\])? # CRC + .*? # Separator and EOL '''), - - ('anime_codec_crc', - ''' - ^(?:\[(?P<release_group>.*?)\][ ._-]*)? - (?:(?P<series_name>.*?)[ ._-]*)? - (?:(?P<ep_ab_num>(((?!(1080|720|480)[pi])|(?![hx].?264))\d{1,3}))[ ._-]*).+? - (?:\[(?P<codec>.*?)\][ ._-]*) - (?:\[(?P<crc>\w{8})\])? - .*? - '''), - ('anime_and_normal', # Bleach - s16e03-04 - 313-314 # Bleach.s16e03-04.313-314 # Bleach s16e03e04 313-314 ''' - ^(?P<series_name>.+?)[ ._-]+ # start of string and series name and non optinal separator - [sS](?P<season_num>\d+)[. _-]* # S01 and optional separator - [eE](?P<ep_num>\d+) # epipisode E02 - (([. _-]*e|-) # linking e/- char - (?P<extra_ep_num>\d+))* # additional E03/etc - ([ ._-]{2,}|[ ._]+) # if "-" is used to separate at least something else has to be there(->{2,}) "s16e03-04-313-314" would make sens any way - ((?P<ep_ab_num>((?!(1080|720|480)[pi])|(?![hx].?264))\d{1,3}))? # absolute number - (-(?P<extra_ab_ep_num>((?!(1080|720|480)[pi])|(?![hx].?264))\d{1,3}))? # "-" as separator and anditional absolute number, all optinal - (v(?P<version>[0-9]))? # the version e.g. "v2" + ^(?P<series_name>.+?)[ ._-]+ # start of string and series name and non optinal separator + [sS](?P<season_num>\d+)[. _-]* # S01 and optional separator + [eE](?P<ep_num>\d+) # epipisode E02 + (([. _-]*e|-) # linking e/- char + (?P<extra_ep_num>\d+))* # additional E03/etc + ([ ._-]{2,}|[ ._]+) # if "-" is used to separate at least something else has to be + # there(->{2,}) "s16e03-04-313-314" would make sens any way + (?P<ep_ab_num>\d{1,3}) # absolute number + (-(?P<extra_ab_ep_num>\d{1,3}))* # "-" as separator and anditional absolute number, all optinal + (v(?P<version>[0-9]))? # the version e.g. "v2" .*? ''' - ), - ('anime_and_normal_x', # Bleach - s16e03-04 - 313-314 # Bleach.s16e03-04.313-314 # Bleach s16e03e04 313-314 ''' - ^(?P<series_name>.+?)[ ._-]+ # start of string and series name and non optinal separator - (?P<season_num>\d+)[. _-]* # S01 and optional separator - [xX](?P<ep_num>\d+) # epipisode E02 - (([. _-]*e|-) # linking e/- char - (?P<extra_ep_num>\d+))* # additional E03/etc - ([ ._-]{2,}|[ ._]+) # if "-" is used to separate at least something else has to be there(->{2,}) "s16e03-04-313-314" would make sens any way - ((?P<ep_ab_num>((?!(1080|720|480)[pi])|(?![hx].?264))\d{1,3}))? # absolute number - (-(?P<extra_ab_ep_num>((?!(1080|720|480)[pi])|(?![hx].?264))\d{1,3}))? # "-" as separator and anditional absolute number, all optinal - (v(?P<version>[0-9]))? # the version e.g. "v2" + ^(?P<series_name>.+?)[ ._-]+ # start of string and series name and non optinal separator + (?P<season_num>\d+)[. _-]* # S01 and optional separator + [xX](?P<ep_num>\d+) # epipisode E02 + (([. _-]*e|-) # linking e/- char + (?P<extra_ep_num>\d+))* # additional E03/etc + ([ ._-]{2,}|[ ._]+) # if "-" is used to separate at least something else has to be + # there(->{2,}) "s16e03-04-313-314" would make sens any way + (?P<ep_ab_num>\d{1,3}) # absolute number + (-(?P<extra_ab_ep_num>\d{1,3}))* # "-" as separator and anditional absolute number, all optinal + (v(?P<version>[0-9]))? # the version e.g. "v2" .*? ''' - ), - ('anime_and_normal_reverse', # Bleach - 313-314 - s16e03-04 ''' - ^(?P<series_name>.+?)[ ._-]+ # start of string and series name and non optinal separator - (?P<ep_ab_num>((?!(1080|720|480)[pi])|(?![hx].?264))\d{1,3}) # absolute number - (-(?P<extra_ab_ep_num>((?!(1080|720|480)[pi])|(?![hx].?264))\d{1,3}))? # "-" as separator and anditional absolute number, all optinal - (v(?P<version>[0-9]))? # the version e.g. "v2" - ([ ._-]{2,}|[ ._]+) # if "-" is used to separate at least something else has to be there(->{2,}) "s16e03-04-313-314" would make sens any way - [sS](?P<season_num>\d+)[. _-]* # S01 and optional separator - [eE](?P<ep_num>\d+) # epipisode E02 - (([. _-]*e|-) # linking e/- char - (?P<extra_ep_num>\d+))* # additional E03/etc + ^(?P<series_name>.+?)[ ._-]+ # start of string and series name and non optinal separator + (?P<ep_ab_num>\d{1,3}) # absolute number + (-(?P<extra_ab_ep_num>\d{1,3}))* # "-" as separator and anditional absolute number, all optinal + (v(?P<version>[0-9]))? # the version e.g. "v2" + ([ ._-]{2,}|[ ._]+) # if "-" is used to separate at least something else has to be + # there(->{2,}) "s16e03-04-313-314" would make sens any way + [sS](?P<season_num>\d+)[. _-]* # S01 and optional separator + [eE](?P<ep_num>\d+) # epipisode E02 + (([. _-]*e|-) # linking e/- char + (?P<extra_ep_num>\d+))* # additional E03/etc .*? ''' ), - ('anime_and_normal_front', # 165.Naruto Shippuuden.s08e014 ''' - ^(?P<ep_ab_num>((?!(1080|720|480)[pi])|(?![hx].?264))\d{1,3}) # start of string and absolute number - (-(?P<extra_ab_ep_num>((?!(1080|720|480)[pi])|(?![hx].?264))\d{1,3}))? # "-" as separator and anditional absolute number, all optinal + ^(?P<ep_ab_num>\d{1,3}) # start of string and absolute number + (-(?P<extra_ab_ep_num>\d{1,3}))* # "-" as separator and anditional absolute number, all optinal (v(?P<version>[0-9]))?[ ._-]+ # the version e.g. "v2" (?P<series_name>.+?)[ ._-]+ - [sS](?P<season_num>\d+)[. _-]* # S01 and optional separator + [sS](?P<season_num>\d+)[. _-]* # S01 and optional separator [eE](?P<ep_num>\d+) - (([. _-]*e|-) # linking e/- char - (?P<extra_ep_num>\d+))* # additional E03/etc + (([. _-]*e|-) # linking e/- char + (?P<extra_ep_num>\d+))* # additional E03/etc .*? ''' ), - ('anime_ep_name', ''' - ^(?:\[(?P<release_group>.+?)\][ ._-]*) - (?P<series_name>.+?)[ ._-]+ - (?P<ep_ab_num>((?!(1080|720|480)[pi])|(?![hx].?264))\d{1,3}) - (-(?P<extra_ab_ep_num>((?!(1080|720|480)[pi])|(?![hx].?264))\d{1,3}))?[ ._-]*? - (?:v(?P<version>[0-9])[ ._-]+?)? - (?:.+?[ ._-]+?)? - \[(?P<extra_info>\w+)\][ ._-]? - (?:\[(?P<crc>\w{8})\])? - .*? + ^(?:\[(?P<release_group>.+?)\][ ._-]*) + (?P<series_name>.+?)[ ._-]+ + (?P<ep_ab_num>\d{1,3}) + (-(?P<extra_ab_ep_num>\d{1,3}))*[ ._-]*? + (?:v(?P<version>[0-9])[ ._-]+?)? + (?:.+?[ ._-]+?)? + \[(?P<extra_info>\w+)\][ ._-]? + (?:\[(?P<crc>\w{8})\])? + .*? ''' ), - ('anime_bare', # One Piece - 102 # [ACX]_Wolf's_Spirit_001.mkv ''' ^(\[(?P<release_group>.+?)\][ ._-]*)? - (?P<series_name>.+?)[ ._-]+ # Show_Name and separator - (?P<ep_ab_num>((?!(1080|720|480)[pi])|(?![hx].?264))\d{1,3}) # E01 - (-(?P<extra_ab_ep_num>((?!(1080|720|480)[pi])|(?![hx].?264))\d{1,3}))? # E02 - (v(?P<version>[0-9]))? # v2 - .*? # Separator and EOL - ''') -] + (?P<series_name>.+?)[ ._-]+ # Show_Name and separator + (?<!H.)(?P<ep_ab_num>\d{3})(?!0p) # E01, while avoiding H.264 and 1080p from being matched + (-(?P<extra_ab_ep_num>\d{3}))* # E02 + (v(?P<version>[0-9]))? # v2 + .*? # Separator and EOL + '''), + + ('standard', + # Show.Name.S01E02.Source.Quality.Etc-Group + # Show Name - S01E02 - My Ep Name + # Show.Name.S01.E03.My.Ep.Name + # Show.Name.S01E02E03.Source.Quality.Etc-Group + # Show Name - S01E02-03 - My Ep Name + # Show.Name.S01.E02.E03 + ''' + ^((?P<series_name>.+?)[. _-]+)? # Show_Name and separator + s(?P<season_num>\d+)[. _-]* # S01 and optional separator + e(?P<ep_num>\d+) # E02 and separator + (([. _-]*e|-) # linking e/- char + (?P<extra_ep_num>(?!(1080|720|480)[pi])\d+))* # additional E03/etc + [. _-]*((?P<extra_info>.+?) # Source_Quality_Etc- + ((?<![. _-])(?<!WEB) # Make sure this is really the release group + -(?P<release_group>[^- ]+))?)?$ # Group + ''' + ), +] \ No newline at end of file diff --git a/tests/name_parser_tests.py b/tests/name_parser_tests.py index 821fed19..2fa64f56 100644 --- a/tests/name_parser_tests.py +++ b/tests/name_parser_tests.py @@ -3,163 +3,244 @@ import unittest import test_lib as test import sys, os.path + sys.path.append(os.path.abspath('..')) sys.path.append(os.path.abspath('../lib')) from sickbeard.name_parser import parser import sickbeard + sickbeard.SYS_ENCODING = 'UTF-8' DEBUG = VERBOSE = False simple_test_cases = { - 'standard': { - 'Mr.Show.Name.S01E02.Source.Quality.Etc-Group': parser.ParseResult(None, 'Mr Show Name', 1, [2], 'Source.Quality.Etc', 'Group'), - 'Show.Name.S01E02': parser.ParseResult(None, 'Show Name', 1, [2]), - 'Show Name - S01E02 - My Ep Name': parser.ParseResult(None, 'Show Name', 1, [2], 'My Ep Name'), - 'Show.1.0.Name.S01.E03.My.Ep.Name-Group': parser.ParseResult(None, 'Show 1.0 Name', 1, [3], 'My.Ep.Name', 'Group'), - 'Show.Name.S01E02E03.Source.Quality.Etc-Group': parser.ParseResult(None, 'Show Name', 1, [2,3], 'Source.Quality.Etc', 'Group'), - 'Mr. Show Name - S01E02-03 - My Ep Name': parser.ParseResult(None, 'Mr. Show Name', 1, [2,3], 'My Ep Name'), - 'Show.Name.S01.E02.E03': parser.ParseResult(None, 'Show Name', 1, [2,3]), - 'Show.Name-0.2010.S01E02.Source.Quality.Etc-Group': parser.ParseResult(None, 'Show Name-0 2010', 1, [2], 'Source.Quality.Etc', 'Group'), - 'S01E02 Ep Name': parser.ParseResult(None, None, 1, [2], 'Ep Name'), - 'Show Name - S06E01 - 2009-12-20 - Ep Name': parser.ParseResult(None, 'Show Name', 6, [1], '2009-12-20 - Ep Name'), - 'Show Name - S06E01 - -30-': parser.ParseResult(None, 'Show Name', 6, [1], '30-' ), - 'Show-Name-S06E01-720p': parser.ParseResult(None, 'Show-Name', 6, [1], '720p' ), - 'Show-Name-S06E01-1080i': parser.ParseResult(None, 'Show-Name', 6, [1], '1080i' ), - 'Show.Name.S06E01.Other.WEB-DL': parser.ParseResult(None, 'Show Name', 6, [1], 'Other.WEB-DL' ), - 'Show.Name.S06E01 Some-Stuff Here': parser.ParseResult(None, 'Show Name', 6, [1], 'Some-Stuff Here' ), - }, - - 'fov': { - 'Show_Name.1x02.Source_Quality_Etc-Group': parser.ParseResult(None, 'Show Name', 1, [2], 'Source_Quality_Etc', 'Group'), - 'Show Name 1x02': parser.ParseResult(None, 'Show Name', 1, [2]), - 'Show Name 1x02 x264 Test': parser.ParseResult(None, 'Show Name', 1, [2], 'x264 Test'), - 'Show Name - 1x02 - My Ep Name': parser.ParseResult(None, 'Show Name', 1, [2], 'My Ep Name'), - 'Show_Name.1x02x03x04.Source_Quality_Etc-Group': parser.ParseResult(None, 'Show Name', 1, [2,3,4], 'Source_Quality_Etc', 'Group'), - 'Show Name - 1x02-03-04 - My Ep Name': parser.ParseResult(None, 'Show Name', 1, [2,3,4], 'My Ep Name'), - '1x02 Ep Name': parser.ParseResult(None, None, 1, [2], 'Ep Name'), - 'Show-Name-1x02-720p': parser.ParseResult(None, 'Show-Name', 1, [2], '720p'), - 'Show-Name-1x02-1080i': parser.ParseResult(None, 'Show-Name', 1, [2], '1080i'), - 'Show Name [05x12] Ep Name': parser.ParseResult(None, 'Show Name', 5, [12], 'Ep Name'), - 'Show.Name.1x02.WEB-DL': parser.ParseResult(None, 'Show Name', 1, [2], 'WEB-DL'), - }, + 'standard': { + 'Mr.Show.Name.S01E02.Source.Quality.Etc-Group': parser.ParseResult(None, 'Mr Show Name', 1, [2], 'Source.Quality.Etc', 'Group'), + 'Show.Name.S01E02': parser.ParseResult(None, 'Show Name', 1, [2]), + 'Show Name - S01E02 - My Ep Name': parser.ParseResult(None, 'Show Name', 1, [2], 'My Ep Name'), + 'Show.1.0.Name.S01.E03.My.Ep.Name-Group': parser.ParseResult(None, 'Show 1.0 Name', 1, [3], 'My.Ep.Name', 'Group'), + 'Show.Name.S01E02E03.Source.Quality.Etc-Group': parser.ParseResult(None, 'Show Name', 1, [2, 3], 'Source.Quality.Etc', 'Group'), + 'Mr. Show Name - S01E02-03 - My Ep Name': parser.ParseResult(None, 'Mr. Show Name', 1, [2, 3], 'My Ep Name'), + 'Show.Name.S01.E02.E03': parser.ParseResult(None, 'Show Name', 1, [2, 3]), + 'Show.Name-0.2010.S01E02.Source.Quality.Etc-Group': parser.ParseResult(None, 'Show Name-0 2010', 1, [2], 'Source.Quality.Etc', 'Group'), + 'S01E02 Ep Name': parser.ParseResult(None, None, 1, [2], 'Ep Name'), + 'Show Name - S06E01 - 2009-12-20 - Ep Name': parser.ParseResult(None, 'Show Name', 6, [1], '2009-12-20 - Ep Name'), + 'Show Name - S06E01 - -30-': parser.ParseResult(None, 'Show Name', 6, [1], '30-'), + 'Show-Name-S06E01-720p': parser.ParseResult(None, 'Show-Name', 6, [1], '720p'), + 'Show-Name-S06E01-1080i': parser.ParseResult(None, 'Show-Name', 6, [1], '1080i'), + 'Show.Name.S06E01.Other.WEB-DL': parser.ParseResult(None, 'Show Name', 6, [1], 'Other.WEB-DL'), + 'Show.Name.S06E01 Some-Stuff Here': parser.ParseResult(None, 'Show Name', 6, [1], 'Some-Stuff Here'), + }, - 'standard_repeat': { - 'Show.Name.S01E02.S01E03.Source.Quality.Etc-Group': parser.ParseResult(None, 'Show Name', 1, [2,3], 'Source.Quality.Etc', 'Group'), - 'Show.Name.S01E02.S01E03': parser.ParseResult(None, 'Show Name', 1, [2,3]), - 'Show Name - S01E02 - S01E03 - S01E04 - Ep Name': parser.ParseResult(None, 'Show Name', 1, [2,3,4], 'Ep Name'), - 'Show.Name.S01E02.S01E03.WEB-DL': parser.ParseResult(None, 'Show Name', 1, [2,3], 'WEB-DL'), - }, - - 'fov_repeat': { - 'Show.Name.1x02.1x03.Source.Quality.Etc-Group': parser.ParseResult(None, 'Show Name', 1, [2,3], 'Source.Quality.Etc', 'Group'), - 'Show.Name.1x02.1x03': parser.ParseResult(None, 'Show Name', 1, [2,3]), - 'Show Name - 1x02 - 1x03 - 1x04 - Ep Name': parser.ParseResult(None, 'Show Name', 1, [2,3,4], 'Ep Name'), - 'Show.Name.1x02.1x03.WEB-DL': parser.ParseResult(None, 'Show Name', 1, [2,3], 'WEB-DL'), - }, + 'fov': { + 'Show_Name.1x02.Source_Quality_Etc-Group': parser.ParseResult(None, 'Show Name', 1, [2], 'Source_Quality_Etc', 'Group'), + 'Show Name 1x02': parser.ParseResult(None, 'Show Name', 1, [2]), + 'Show Name 1x02 x264 Test': parser.ParseResult(None, 'Show Name', 1, [2], 'x264 Test'), + 'Show Name - 1x02 - My Ep Name': parser.ParseResult(None, 'Show Name', 1, [2], 'My Ep Name'), + 'Show_Name.1x02x03x04.Source_Quality_Etc-Group': parser.ParseResult(None, 'Show Name', 1, [2, 3, 4], 'Source_Quality_Etc', 'Group'), + 'Show Name - 1x02-03-04 - My Ep Name': parser.ParseResult(None, 'Show Name', 1, [2, 3, 4], 'My Ep Name'), + '1x02 Ep Name': parser.ParseResult(None, None, 1, [2], 'Ep Name'), + 'Show-Name-1x02-720p': parser.ParseResult(None, 'Show-Name', 1, [2], '720p'), + 'Show-Name-1x02-1080i': parser.ParseResult(None, 'Show-Name', 1, [2], '1080i'), + 'Show Name [05x12] Ep Name': parser.ParseResult(None, 'Show Name', 5, [12], 'Ep Name'), + 'Show.Name.1x02.WEB-DL': parser.ParseResult(None, 'Show Name', 1, [2], 'WEB-DL'), + }, - 'bare': { - 'Show.Name.102.Source.Quality.Etc-Group': parser.ParseResult(None, 'Show Name', 1, [2], 'Source.Quality.Etc', 'Group'), - 'show.name.2010.123.source.quality.etc-group': parser.ParseResult(None, 'show name 2010', 1, [23], 'source.quality.etc', 'group'), - 'show.name.2010.222.123.source.quality.etc-group': parser.ParseResult(None, 'show name 2010.222', 1, [23], 'source.quality.etc', 'group'), - 'Show.Name.102': parser.ParseResult(None, 'Show Name', 1, [2]), - 'the.event.401.hdtv-lol': parser.ParseResult(None, 'the event', 4, [1], 'hdtv', 'lol'), - 'show.name.2010.special.hdtv-blah': None, - }, - - 'stupid': { - 'tpz-abc102': parser.ParseResult(None, None, 1, [2], None, 'tpz'), - 'tpz-abc.102': parser.ParseResult(None, None, 1, [2], None, 'tpz'), - }, - - 'no_season': { - 'Show Name - 01 - Ep Name': parser.ParseResult(None, 'Show Name', None, [1], 'Ep Name'), - '01 - Ep Name': parser.ParseResult(None, None, None, [1], 'Ep Name'), - 'Show Name - 01 - Ep Name - WEB-DL': parser.ParseResult(None, 'Show Name', None, [1], 'Ep Name - WEB-DL'), - }, + 'standard_repeat': { + 'Show.Name.S01E02.S01E03.Source.Quality.Etc-Group': parser.ParseResult(None, 'Show Name', 1, [2, 3], 'Source.Quality.Etc', 'Group'), + 'Show.Name.S01E02.S01E03': parser.ParseResult(None, 'Show Name', 1, [2, 3]), + 'Show Name - S01E02 - S01E03 - S01E04 - Ep Name': parser.ParseResult(None, 'Show Name', 1, [2, 3, 4], 'Ep Name'), + 'Show.Name.S01E02.S01E03.WEB-DL': parser.ParseResult(None, 'Show Name', 1, [2, 3], 'WEB-DL'), + }, - 'no_season_general': { - 'Show.Name.E23.Source.Quality.Etc-Group': parser.ParseResult(None, 'Show Name', None, [23], 'Source.Quality.Etc', 'Group'), - 'Show Name - Episode 01 - Ep Name': parser.ParseResult(None, 'Show Name', None, [1], 'Ep Name'), - 'Show.Name.Part.3.Source.Quality.Etc-Group': parser.ParseResult(None, 'Show Name', None, [3], 'Source.Quality.Etc', 'Group'), - 'Show.Name.Part.1.and.Part.2.Blah-Group': parser.ParseResult(None, 'Show Name', None, [1,2], 'Blah', 'Group'), - 'Show.Name.Part.IV.Source.Quality.Etc-Group': parser.ParseResult(None, 'Show Name', None, [4], 'Source.Quality.Etc', 'Group'), - 'Deconstructed.E07.1080i.HDTV.DD5.1.MPEG2-TrollHD': parser.ParseResult(None, 'Deconstructed', None, [7], '1080i.HDTV.DD5.1.MPEG2', 'TrollHD'), - 'Show.Name.E23.WEB-DL': parser.ParseResult(None, 'Show Name', None, [23], 'WEB-DL'), - }, + 'fov_repeat': { + 'Show.Name.1x02.1x03.Source.Quality.Etc-Group': parser.ParseResult(None, 'Show Name', 1, [2, 3], 'Source.Quality.Etc', 'Group'), + 'Show.Name.1x02.1x03': parser.ParseResult(None, 'Show Name', 1, [2, 3]), + 'Show Name - 1x02 - 1x03 - 1x04 - Ep Name': parser.ParseResult(None, 'Show Name', 1, [2, 3, 4], 'Ep Name'), + 'Show.Name.1x02.1x03.WEB-DL': parser.ParseResult(None, 'Show Name', 1, [2, 3], 'WEB-DL'), + }, - 'no_season_multi_ep': { - 'Show.Name.E23-24.Source.Quality.Etc-Group': parser.ParseResult(None, 'Show Name', None, [23,24], 'Source.Quality.Etc', 'Group'), - 'Show Name - Episode 01-02 - Ep Name': parser.ParseResult(None, 'Show Name', None, [1,2], 'Ep Name'), - 'Show.Name.E23-24.WEB-DL': parser.ParseResult(None, 'Show Name', None, [23,24], 'WEB-DL'), - }, + 'bare': { + 'Show.Name.102.Source.Quality.Etc-Group': parser.ParseResult(None, 'Show Name', 1, [2], 'Source.Quality.Etc', 'Group'), + 'show.name.2010.123.source.quality.etc-group': parser.ParseResult(None, 'show name 2010', 1, [23], 'source.quality.etc', 'group'), + 'show.name.2010.222.123.source.quality.etc-group': parser.ParseResult(None, 'show name 2010.222', 1, [23], 'source.quality.etc', 'group'), + 'Show.Name.102': parser.ParseResult(None, 'Show Name', 1, [2]), + 'the.event.401.hdtv-lol': parser.ParseResult(None, 'the event', 4, [1], 'hdtv', 'lol'), + # 'show.name.2010.special.hdtv-blah': None, + }, - 'season_only': { - 'Show.Name.S02.Source.Quality.Etc-Group': parser.ParseResult(None, 'Show Name', 2, [], 'Source.Quality.Etc', 'Group'), - 'Show Name Season 2': parser.ParseResult(None, 'Show Name', 2), - 'Season 02': parser.ParseResult(None, None, 2), - }, - - 'scene_date_format': { - 'Show.Name.2010.11.23.Source.Quality.Etc-Group': parser.ParseResult(None, 'Show Name', None, [], 'Source.Quality.Etc', 'Group', datetime.date(2010,11,23)), - 'Show Name - 2010.11.23': parser.ParseResult(None, 'Show Name', air_date = datetime.date(2010,11,23)), - 'Show.Name.2010.23.11.Source.Quality.Etc-Group': parser.ParseResult(None, 'Show Name', None, [], 'Source.Quality.Etc', 'Group', datetime.date(2010,11,23)), - 'Show Name - 2010-11-23 - Ep Name': parser.ParseResult(None, 'Show Name', extra_info = 'Ep Name', air_date = datetime.date(2010,11,23)), - '2010-11-23 - Ep Name': parser.ParseResult(None, extra_info = 'Ep Name', air_date = datetime.date(2010,11,23)), - 'Show.Name.2010.11.23.WEB-DL': parser.ParseResult(None, 'Show Name', None, [], 'WEB-DL', None, datetime.date(2010,11,23)), - }, - } + 'stupid': { + 'tpz-abc102': parser.ParseResult(None, None, 1, [2], None, 'tpz'), + 'tpz-abc.102': parser.ParseResult(None, None, 1, [2], None, 'tpz'), + }, + + 'no_season': { + 'Show Name - 01 - Ep Name': parser.ParseResult(None, 'Show Name', None, [1], 'Ep Name'), + '01 - Ep Name': parser.ParseResult(None, None, None, [1], 'Ep Name'), + 'Show Name - 01 - Ep Name - WEB-DL': parser.ParseResult(None, 'Show Name', None, [1], 'Ep Name - WEB-DL'), + }, + + 'no_season_general': { + 'Show.Name.E23.Source.Quality.Etc-Group': parser.ParseResult(None, 'Show Name', None, [23], 'Source.Quality.Etc', 'Group'), + 'Show Name - Episode 01 - Ep Name': parser.ParseResult(None, 'Show Name', None, [1], 'Ep Name'), + 'Show.Name.Part.3.Source.Quality.Etc-Group': parser.ParseResult(None, 'Show Name', None, [3], 'Source.Quality.Etc', 'Group'), + 'Show.Name.Part.1.and.Part.2.Blah-Group': parser.ParseResult(None, 'Show Name', None, [1, 2], 'Blah', 'Group'), + 'Show.Name.Part.IV.Source.Quality.Etc-Group': parser.ParseResult(None, 'Show Name', None, [4], 'Source.Quality.Etc', 'Group'), + 'Deconstructed.E07.1080i.HDTV.DD5.1.MPEG2-TrollHD': parser.ParseResult(None, 'Deconstructed', None, [7], '1080i.HDTV.DD5.1.MPEG2', 'TrollHD'), + 'Show.Name.E23.WEB-DL': parser.ParseResult(None, 'Show Name', None, [23], 'WEB-DL'), + }, + + 'no_season_multi_ep': { + 'Show.Name.E23-24.Source.Quality.Etc-Group': parser.ParseResult(None, 'Show Name', None, [23, 24], 'Source.Quality.Etc', 'Group'), + 'Show Name - Episode 01-02 - Ep Name': parser.ParseResult(None, 'Show Name', None, [1, 2], 'Ep Name'), + 'Show.Name.E23-24.WEB-DL': parser.ParseResult(None, 'Show Name', None, [23, 24], 'WEB-DL'), + }, + + 'season_only': { + 'Show.Name.S02.Source.Quality.Etc-Group': parser.ParseResult(None, 'Show Name', 2, [], 'Source.Quality.Etc', 'Group'), + 'Show Name Season 2': parser.ParseResult(None, 'Show Name', 2), + 'Season 02': parser.ParseResult(None, None, 2), + }, + + 'scene_date_format': { + 'Show.Name.2010.11.23.Source.Quality.Etc-Group': parser.ParseResult(None, 'Show Name', None, [], 'Source.Quality.Etc', 'Group', datetime.date(2010, 11, 23)), + 'Show Name - 2010.11.23': parser.ParseResult(None, 'Show Name', air_date=datetime.date(2010, 11, 23)), + 'Show.Name.2010.23.11.Source.Quality.Etc-Group': parser.ParseResult(None, 'Show Name', None, [], 'Source.Quality.Etc', 'Group', datetime.date(2010, 11, 23)), + 'Show Name - 2010-11-23 - Ep Name': parser.ParseResult(None, 'Show Name', extra_info='Ep Name', air_date=datetime.date(2010, 11, 23)), + '2010-11-23 - Ep Name': parser.ParseResult(None, extra_info='Ep Name', air_date=datetime.date(2010, 11, 23)), + 'Show.Name.2010.11.23.WEB-DL': parser.ParseResult(None, 'Show Name', None, [], 'WEB-DL', None, datetime.date(2010, 11, 23)), + }, + + 'anime_ultimate': { + '[Tsuki] Bleach - 301 [1280x720][61D1D4EE]': parser.ParseResult(None, 'Bleach', None, [], '1280x720', 'Tsuki', None, [301]), + '[Tsuki] Fairy Tail - 70 [1280x720][C4807111]': parser.ParseResult(None, 'Fairy Tail', None, [], '1280x720', 'Tsuki', None, [70]), + '[SGKK] Bleach 312v2 [720p MKV]': parser.ParseResult(None, 'Bleach', None, [], '720p MKV', 'SGKK', None, [312]), + '[BSS-Anon] Tengen Toppa Gurren Lagann - 22-23 [1280x720][h264][6039D9AF]': parser.ParseResult(None, 'Tengen Toppa Gurren Lagann', None, [], '1280x720', 'BSS-Anon', None, [22, 23]), + '[SJSUBS]_Naruto_Shippuden_-_02_[480p AAC]': parser.ParseResult(None, 'Naruto Shippuden', None, [], '480p AAC', 'SJSUBS', None, [2]), + '[SFW-Chihiro] Dance in the Vampire Bund - 12 [1920x1080 Blu-ray FLAC][2F6DBC66].mkv': parser.ParseResult(None, 'Dance in the Vampire Bund', None, [], '1920x1080 Blu-ray FLAC', 'SFW-Chihiro', None, [12]), + '[SHiN-gx] Hanasaku Iroha - 01 [1280x720 h.264 AAC][BDC36683]': parser.ParseResult(None, 'Hanasaku Iroha', None, [], '1280x720 h.264 AAC', 'SHiN-gx', None, [1]), + '[SFW-Chihiro] Dance in the Vampire Bund - 02 [1920x1080 Blu-ray FLAC][C1FA0A09]': parser.ParseResult(None, 'Dance in the Vampire Bund', None, [], '1920x1080 Blu-ray FLAC', 'SFW-Chihiro', None, [2]), + '[HorribleSubs] No. 6 - 11 [720p]': parser.ParseResult(None, 'No. 6', None, [], '720p', 'HorribleSubs', None, [11]), + '[HorribleSubs] D Gray-Man - 312 (480p) [F501C9BE]': parser.ParseResult(None, 'D Gray-Man', None, [], '480p', 'HorribleSubs', None, [312]), + '[SGKK] Tengen Toppa Gurren Lagann - 45-46 (720p h264) [F501C9BE]': parser.ParseResult(None, 'Tengen Toppa Gurren Lagann', None, [], '720p h264', 'SGKK', None, [45, 46]), + '[Stratos-Subs]_Infinite_Stratos_-_12_(1280x720_H.264_AAC)_[379759DB]': parser.ParseResult(None, 'Infinite Stratos', None, [], '1280x720_H.264_AAC', 'Stratos-Subs', None, [12]), + '[ShinBunBu-Subs] Bleach - 02-03 (CX 1280x720 x264 AAC)': parser.ParseResult(None, 'Bleach', None, [], 'CX 1280x720 x264 AAC', 'ShinBunBu-Subs', None, [02, 03]), + '[Doki] Hanasaku Iroha - 03 (848x480 h264 AAC) [CB1AA73B]': parser.ParseResult(None, 'Hanasaku Iroha', None, [], '848x480 h264 AAC', 'Doki', None, [03]), + '[UTW]_Fractal_-_01_[h264-720p][96D3F1BF]': parser.ParseResult(None, 'Fractal', None, [], 'h264-720p', 'UTW', None, [1]), + '[a-s]_inuyasha_-_028_rs2_[BFDDF9F2]': parser.ParseResult(None, 'inuyasha', None, [], 'BFDDF9F2', 'a-s', None, [28]), + '[HorribleSubs] Fairy Tail S2 - 37 [1080p]': parser.ParseResult(None,'Fairy Tail S2', None, [], '1080p', 'HorribleSubs', None, [37]), + '[HorribleSubs] Sword Art Online II - 23 [720p]': parser.ParseResult(None, 'Sword Art Online II', None, [], '720p', 'HorribleSubs', None, [23]) + }, + + 'anime_ep_name': { + '[TzaTziki]_One_Piece_279_Chopper_Man_1_[720p][8AE5F25D]': parser.ParseResult(None, 'One Piece', None, [], '720p', 'TzaTziki', None, [279]), + "[ACX]Wolf's_Rain_-_04_-_Scars_in_the_Wasteland_[octavarium]_[82B7E357]": parser.ParseResult(None, "Wolf's Rain", None, [], 'octavarium', 'ACX', None, [4]), + '[ACX]Black Lagoon - 02v2 - Mangrove Heaven [SaintDeath] [7481F875]': parser.ParseResult(None, 'Black Lagoon', None, [], 'SaintDeath', 'ACX', None, [2]), + }, + + "anime_standard_round": { + '[SGKK] Bleach - 312v2 (1280x720 h264 AAC) [F501C9BE]': parser.ParseResult(None, 'Bleach', None, [], '1280x720 h264 AAC', 'SGKK', None, [312]), + }, + + 'anime_slash': { + '[SGKK] Bleach 312v1 [720p/MKV]': parser.ParseResult(None, 'Bleach', None, [], '720p', 'SGKK', None, [312]), + '[SGKK] Bleach 312 [480p/MKV]': parser.ParseResult(None, 'Bleach', None, [], '480p', 'SGKK', None, [312]) + }, + + 'anime_standard_codec': { + '[Ayako]_Infinite_Stratos_-_IS_-_07_[H264][720p][EB7838FC]': parser.ParseResult(None, 'Infinite Stratos', None, [], '720p', 'Ayako', None, [7]), + '[Ayako] Infinite Stratos - IS - 07v2 [H264][720p][44419534]': parser.ParseResult(None, 'Infinite Stratos', None, [], '720p', 'Ayako', None, [7]), + '[Ayako-Shikkaku] Oniichan no Koto Nanka Zenzen Suki Janain Dakara ne - 10 [LQ][h264][720p] [8853B21C]': parser.ParseResult(None, 'Oniichan no Koto Nanka Zenzen Suki Janain Dakara ne', None, [], '720p', 'Ayako-Shikkaku', None, [10]), + '[Tsuki] Fairy Tail - 72 [XviD][C4807111]': parser.ParseResult(None, 'Fairy Tail', None, [], 'C4807111', 'Tsuki', None, [72]), + 'Bubblegum Crisis Tokyo 2040 - 25 [aX] [F4E2E558]': parser.ParseResult(None, 'Bubblegum Crisis Tokyo 2040', None, [], "aX", None, None, [25]), + + }, + + 'anime_and_normal': { + 'Bleach - s02e03 - 012 - Name & Name': parser.ParseResult(None, 'Bleach', 2, [3], None, None, None, [12]), + 'Bleach - s02e03e04 - 012-013 - Name & Name': parser.ParseResult(None, 'Bleach', 2, [3, 4], None, None, None, [12, 13]), + 'Bleach - s16e03-04 - 313-314': parser.ParseResult(None, 'Bleach', 16, [3, 4], None, None, None, [313, 314]), + 'Blue Submarine No. 6 s16e03e04 313-314': parser.ParseResult(None, 'Blue Submarine No. 6', 16, [3, 4], None, None, None, [313, 314]), + 'Bleach.s16e03-04.313-314': parser.ParseResult(None, 'Bleach', 16, [3, 4], None, None, None, [313, 314]), + '.hack roots s01e01 001.mkv': parser.ParseResult(None, 'hack roots', 1, [1], None, None, None, [1]), + '.hack sign s01e01 001.mkv': parser.ParseResult(None, 'hack sign', 1, [1], None, None, None, [1]) + + }, + + 'anime_and_normal_reverse': { + 'Bleach - 012 - s02e03 - Name & Name': parser.ParseResult(None, 'Bleach', 2, [3], None, None, None, [12]), + 'Blue Submarine No. 6 - 012-013 - s02e03e04 - Name & Name': parser.ParseResult(None, 'Blue Submarine No. 6', 2, [3, 4], None, None, None, [12, 13]), + '07-GHOST - 012-013 - s02e03e04 - Name & Name': parser.ParseResult(None, '07-GHOST', 2, [3, 4], None, None, None, [12, 13]), + '3x3 Eyes - 012-013 - s02e03-04 - Name & Name': parser.ParseResult(None, '3x3 Eyes', 2, [3, 4], None, None, None, [12, 13]), + }, + + 'anime_and_normal_front': { + '165.Naruto Shippuuden.s08e014': parser.ParseResult(None, 'Naruto Shippuuden', 8, [14], None, None, None, [165]), + '165-166.Naruto Shippuuden.s08e014e015': parser.ParseResult(None, 'Naruto Shippuuden', 8, [14, 15], None, None, None, [165, 166]), + '165-166.07-GHOST.s08e014-015': parser.ParseResult(None, '07-GHOST', 8, [14, 15], None, None, None, [165, 166]), + '165-166.3x3 Eyes.S08E014E015': parser.ParseResult(None, '3x3 Eyes', 8, [14, 15], None, None, None, [165, 166]), + }, + + 'anime_bare': { + 'One Piece 102': parser.ParseResult(None, 'One Piece', None, [], None, None, None, [102]), + 'bleach - 010': parser.ParseResult(None, 'bleach', None, [], None, None, None, [10]), + 'Naruto Shippuden - 314v2': parser.ParseResult(None, 'Naruto Shippuden', None, [], None, None, None, [314]), + 'Blue Submarine No. 6 104-105': parser.ParseResult(None, 'Blue Submarine No. 6', None, [], None, None, None, [104, 105]), + 'Samurai X: Trust & Betrayal (OVA) 001-002': parser.ParseResult(None, 'Samurai X: Trust & Betrayal (OVA)', None, [], None, None, None, [1, 2]), + "[ACX]_Wolf's_Spirit_001.mkv": parser.ParseResult(None, "Wolf's Spirit", None, [], None, 'ACX', None, [1]) + } + +} combination_test_cases = [ - ('/test/path/to/Season 02/03 - Ep Name.avi', - parser.ParseResult(None, None, 2, [3], 'Ep Name'), - ['no_season', 'season_only']), - - ('Show.Name.S02.Source.Quality.Etc-Group/tpz-sn203.avi', - parser.ParseResult(None, 'Show Name', 2, [3], 'Source.Quality.Etc', 'Group'), - ['stupid', 'season_only']), + ('/test/path/to/Season 02/03 - Ep Name.avi', + parser.ParseResult(None, None, 2, [3], 'Ep Name'), + ['no_season', 'season_only']), - ('MythBusters.S08E16.720p.HDTV.x264-aAF/aaf-mb.s08e16.720p.mkv', - parser.ParseResult(None, 'MythBusters', 8, [16], '720p.HDTV.x264', 'aAF'), - ['standard']), - - ('/home/drop/storage/TV/Terminator The Sarah Connor Chronicles/Season 2/S02E06 The Tower is Tall, But the Fall is Short.mkv', - parser.ParseResult(None, None, 2, [6], 'The Tower is Tall, But the Fall is Short'), - ['standard']), - - (r'/Test/TV/Jimmy Fallon/Season 2/Jimmy Fallon - 2010-12-15 - blah.avi', - parser.ParseResult(None, 'Jimmy Fallon', extra_info = 'blah', air_date = datetime.date(2010,12,15)), - ['scene_date_format']), + ('Show.Name.S02.Source.Quality.Etc-Group/tpz-sn203.avi', + parser.ParseResult(None, 'Show Name', 2, [3], 'Source.Quality.Etc', 'Group'), + ['stupid', 'season_only']), - (r'/X/30 Rock/Season 4/30 Rock - 4x22 -.avi', - parser.ParseResult(None, '30 Rock', 4, [22]), - ['fov']), - - ('Season 2\\Show Name - 03-04 - Ep Name.ext', - parser.ParseResult(None, 'Show Name', 2, [3,4], extra_info = 'Ep Name'), - ['no_season', 'season_only']), - - ('Season 02\\03-04-05 - Ep Name.ext', - parser.ParseResult(None, None, 2, [3,4,5], extra_info = 'Ep Name'), - ['no_season', 'season_only']), - ] + ('MythBusters.S08E16.720p.HDTV.x264-aAF/aaf-mb.s08e16.720p.mkv', + parser.ParseResult(None, 'MythBusters', 8, [16], '720p.HDTV.x264', 'aAF'), + ['standard']), + + ('/home/drop/storage/TV/Terminator The Sarah Connor Chronicles/Season 2/S02E06 The Tower is Tall, But the Fall is Short.mkv', + parser.ParseResult(None, None, 2, [6], 'The Tower is Tall, But the Fall is Short'), + ['standard']), + + (r'/Test/TV/Jimmy Fallon/Season 2/Jimmy Fallon - 2010-12-15 - blah.avi', + parser.ParseResult(None, 'Jimmy Fallon', extra_info='blah', air_date=datetime.date(2010, 12, 15)), + ['scene_date_format']), + + (r'/X/30 Rock/Season 4/30 Rock - 4x22 -.avi', + parser.ParseResult(None, '30 Rock', 4, [22]), + ['fov']), + + ('Season 2\\Show Name - 03-04 - Ep Name.ext', + parser.ParseResult(None, 'Show Name', 2, [3, 4], extra_info='Ep Name'), + ['no_season', 'season_only']), + + ('Season 02\\03-04-05 - Ep Name.ext', + parser.ParseResult(None, None, 2, [3, 4, 5], extra_info='Ep Name'), + ['no_season', 'season_only']), +] unicode_test_cases = [ - (u'The.Big.Bang.Theory.2x07.The.Panty.Pi\xf1ata.Polarization.720p.HDTV.x264.AC3-SHELDON.mkv', - parser.ParseResult(None, 'The.Big.Bang.Theory', 2, [7], '720p.HDTV.x264.AC3', 'SHELDON') - ), - ('The.Big.Bang.Theory.2x07.The.Panty.Pi\xc3\xb1ata.Polarization.720p.HDTV.x264.AC3-SHELDON.mkv', - parser.ParseResult(None, 'The.Big.Bang.Theory', 2, [7], '720p.HDTV.x264.AC3', 'SHELDON') - ), - ] + (u'The.Big.Bang.Theory.2x07.The.Panty.Pi\xf1ata.Polarization.720p.HDTV.x264.AC3-SHELDON.mkv', + parser.ParseResult(None, 'The.Big.Bang.Theory', 2, [7], '720p.HDTV.x264.AC3', 'SHELDON') + ), + ('The.Big.Bang.Theory.2x07.The.Panty.Pi\xc3\xb1ata.Polarization.720p.HDTV.x264.AC3-SHELDON.mkv', + parser.ParseResult(None, 'The.Big.Bang.Theory', 2, [7], '720p.HDTV.x264.AC3', 'SHELDON') + ), +] failure_cases = ['7sins-jfcs01e09-720p-bluray-x264'] class UnicodeTests(test.SickbeardTestDBCase): - def _test_unicode(self, name, result): np = parser.NameParser(True) @@ -170,47 +251,46 @@ class UnicodeTests(test.SickbeardTestDBCase): # this shouldn't raise an exception a = repr(str(parse_result)) - + def test_unicode(self): for (name, result) in unicode_test_cases: self._test_unicode(name, result) + class FailureCaseTests(test.SickbeardTestDBCase): - def _test_name(self, name): np = parser.NameParser(True) try: parse_result = np.parse(name) except (parser.InvalidNameException, parser.InvalidShowException): return True - + if VERBOSE: print 'Actual: ', parse_result.which_regex, parse_result return False - + def test_failures(self): for name in failure_cases: self.assertTrue(self._test_name(name)) + class ComboTests(test.SickbeardTestDBCase): - def _test_combo(self, name, result, which_regexes): - + if VERBOSE: print - print 'Testing', name - + print 'Testing', name + np = parser.NameParser(True) try: test_result = np.parse(name) except parser.InvalidShowException: return False - + if DEBUG: print test_result, test_result.which_regex print result, which_regexes - self.assertEqual(test_result, result) for cur_regex in which_regexes: @@ -218,14 +298,14 @@ class ComboTests(test.SickbeardTestDBCase): self.assertEqual(len(which_regexes), len(test_result.which_regex)) def test_combos(self): - + for (name, result, which_regexes) in combination_test_cases: # Normalise the paths. Converts UNIX-style paths into Windows-style # paths when test is run on Windows. self._test_combo(os.path.normpath(name), result, which_regexes) -class BasicTests(test.SickbeardTestDBCase): +class BasicTests(test.SickbeardTestDBCase): def _test_names(self, np, section, transform=None, verbose=False): if VERBOSE or verbose: @@ -245,109 +325,150 @@ class BasicTests(test.SickbeardTestDBCase): return else: test_result = np.parse(cur_test) - - if DEBUG or verbose: + + try: + # self.assertEqual(test_result.which_regex, [section]) + self.assertEqual(test_result, result) + except: print 'air_by_date:', test_result.is_air_by_date, 'air_date:', test_result.air_date print 'anime:', test_result.is_anime, 'ab_episode_numbers:', test_result.ab_episode_numbers print test_result print result - self.assertEqual(test_result.which_regex, [section]) - self.assertEqual(test_result, result) + raise - #def test_standard_names(self): - # np = parser.NameParser(False) - # self._test_names(np, 'standard') - # - #def test_standard_repeat_names(self): - # np = parser.NameParser(False) - # self._test_names(np, 'standard_repeat') - # - #def test_fov_names(self): - # np = parser.NameParser(False) - # self._test_names(np, 'fov') - # - #def test_fov_repeat_names(self): - # np = parser.NameParser(False) - # self._test_names(np, 'fov_repeat') - # - #def test_bare_names(self): - # np = parser.NameParser(False) - # self._test_names(np, 'bare') - # - #def test_stupid_names(self): - # np = parser.NameParser(False) - # self._test_names(np, 'stupid') - # - #def test_no_season_names(self): - # np = parser.NameParser(False) - # self._test_names(np, 'no_season') - # - #def test_no_season_general_names(self): - # np = parser.NameParser(False) - # self._test_names(np, 'no_season_general') - # - #def test_no_season_multi_ep_names(self): - # np = parser.NameParser(False) - # self._test_names(np, 'no_season_multi_ep') - # - #def test_season_only_names(self): - # np = parser.NameParser(False) - # self._test_names(np, 'season_only') - # - #def test_scene_date_format_names(self): - # np = parser.NameParser(False) - # self._test_names(np, 'scene_date_format') - # - #def test_standard_file_names(self): - # np = parser.NameParser() - # self._test_names(np, 'standard', lambda x: x + '.avi') - # - #def test_standard_repeat_file_names(self): - # np = parser.NameParser() - # self._test_names(np, 'standard_repeat', lambda x: x + '.avi') - # - #def test_fov_file_names(self): - # np = parser.NameParser() - # self._test_names(np, 'fov', lambda x: x + '.avi') - # - #def test_fov_repeat_file_names(self): - # np = parser.NameParser() - # self._test_names(np, 'fov_repeat', lambda x: x + '.avi') - # - #def test_bare_file_names(self): - # np = parser.NameParser() - # self._test_names(np, 'bare', lambda x: x + '.avi') - # - #def test_stupid_file_names(self): - # np = parser.NameParser() - # self._test_names(np, 'stupid', lambda x: x + '.avi') - # - #def test_no_season_file_names(self): - # np = parser.NameParser() - # self._test_names(np, 'no_season', lambda x: x + '.avi') - # - #def test_no_season_general_file_names(self): - # np = parser.NameParser() - # self._test_names(np, 'no_season_general', lambda x: x + '.avi') - # - #def test_no_season_multi_ep_file_names(self): - # np = parser.NameParser() - # self._test_names(np, 'no_season_multi_ep', lambda x: x + '.avi') - # - #def test_season_only_file_names(self): - # np = parser.NameParser() - # self._test_names(np, 'season_only', lambda x: x + '.avi') - # - #def test_scene_date_format_file_names(self): - # np = parser.NameParser() - # self._test_names(np, 'scene_date_format', lambda x: x + '.avi') + + def test_standard_names(self): + np = parser.NameParser(False, testing=True) + self._test_names(np, 'standard') + + def test_standard_repeat_names(self): + np = parser.NameParser(False, testing=True) + self._test_names(np, 'standard_repeat') + + def test_fov_names(self): + np = parser.NameParser(False, testing=True) + self._test_names(np, 'fov') + + def test_fov_repeat_names(self): + np = parser.NameParser(False, testing=True) + self._test_names(np, 'fov_repeat') + + def test_bare_names(self): + np = parser.NameParser(False, testing=True) + self._test_names(np, 'bare') + + def test_stupid_names(self): + np = parser.NameParser(False, testing=True) + self._test_names(np, 'stupid') + + def test_no_season_names(self): + np = parser.NameParser(False, testing=True) + self._test_names(np, 'no_season') + + def test_no_season_general_names(self): + np = parser.NameParser(False, testing=True) + self._test_names(np, 'no_season_general') + + def test_no_season_multi_ep_names(self): + np = parser.NameParser(False, testing=True) + self._test_names(np, 'no_season_multi_ep') + + def test_season_only_names(self): + np = parser.NameParser(False, testing=True) + self._test_names(np, 'season_only') + + def test_scene_date_format_names(self): + np = parser.NameParser(False, testing=True) + self._test_names(np, 'scene_date_format') + + def test_standard_file_names(self): + np = parser.NameParser(testing=True) + self._test_names(np, 'standard', lambda x: x + '.avi') + + def test_standard_repeat_file_names(self): + np = parser.NameParser(testing=True) + self._test_names(np, 'standard_repeat', lambda x: x + '.avi') + + def test_fov_file_names(self): + np = parser.NameParser(testing=True) + self._test_names(np, 'fov', lambda x: x + '.avi') + + def test_fov_repeat_file_names(self): + np = parser.NameParser(testing=True) + self._test_names(np, 'fov_repeat', lambda x: x + '.avi') + + def test_bare_file_names(self): + np = parser.NameParser(testing=True) + self._test_names(np, 'bare', lambda x: x + '.avi') + + def test_stupid_file_names(self): + np = parser.NameParser(testing=True) + self._test_names(np, 'stupid', lambda x: x + '.avi') + + def test_no_season_file_names(self): + np = parser.NameParser(testing=True) + self._test_names(np, 'no_season', lambda x: x + '.avi') + + def test_no_season_general_file_names(self): + np = parser.NameParser(testing=True) + self._test_names(np, 'no_season_general', lambda x: x + '.avi') + + def test_no_season_multi_ep_file_names(self): + np = parser.NameParser(testing=True) + self._test_names(np, 'no_season_multi_ep', lambda x: x + '.avi') + + def test_season_only_file_names(self): + np = parser.NameParser(testing=True) + self._test_names(np, 'season_only', lambda x: x + '.avi') + + def test_scene_date_format_file_names(self): + np = parser.NameParser(testing=True) + self._test_names(np, 'scene_date_format', lambda x: x + '.avi') def test_combination_names(self): pass + def test_anime_ultimate(self): + np = parser.NameParser(False, TVShow(is_anime=True), testing=True) + self._test_names(np, 'anime_ultimate') + + def test_anime_ep_name(self): + np = parser.NameParser(False, TVShow(is_anime=True), testing=True) + self._test_names(np, 'anime_ep_name') + + def test_anime_slash(self): + np = parser.NameParser(False, TVShow(is_anime=True), testing=True) + self._test_names(np, 'anime_slash') + + def test_anime_codec(self): + np = parser.NameParser(False, TVShow(is_anime=True), testing=True) + self._test_names(np, 'anime_standard_codec') + + def test_anime_and_normal(self): + np = parser.NameParser(False, TVShow(is_anime=True), testing=True) + self._test_names(np, 'anime_and_normal') + + def test_anime_and_normal_reverse(self): + np = parser.NameParser(False, TVShow(is_anime=True), testing=True) + self._test_names(np, 'anime_and_normal_reverse') + + def test_anime_and_normal_front(self): + np = parser.NameParser(False, TVShow(is_anime=True), testing=True) + self._test_names(np, 'anime_and_normal_front') + + def test_anime_bare(self): + np = parser.NameParser(False, TVShow(is_anime=True), testing=True) + self._test_names(np, 'anime_bare') + + +class TVShow(object): + def __init__(self, is_anime=False): + self.is_anime = is_anime + + if __name__ == '__main__': if len(sys.argv) > 1: - suite = unittest.TestLoader().loadTestsFromName('name_parser_tests.BasicTests.test_'+sys.argv[1]) + suite = unittest.TestLoader().loadTestsFromName('name_parser_tests.BasicTests.test_' + sys.argv[1]) else: suite = unittest.TestLoader().loadTestsFromTestCase(BasicTests) unittest.TextTestRunner(verbosity=2).run(suite) From b8804973ca1de9a12fdce68cb2aca748a550fc0f Mon Sep 17 00:00:00 2001 From: Adam <adam111316@users.noreply.github.com> Date: Mon, 29 Dec 2014 12:22:34 +0800 Subject: [PATCH 10/21] Add pull request checkout option to General Config/Advanced Settings --- CHANGES.md | 1 + .../interfaces/default/config_general.tmpl | 18 +++++++++++++ gui/slick/js/config.js | 4 +++ sickbeard/gh_api.py | 25 ++++++++++++++++++- sickbeard/versionChecker.py | 23 ++++++++++++++++- sickbeard/webserve.py | 11 ++++++++ 6 files changed, 80 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 09c4b64a..4ec76cfd 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -15,6 +15,7 @@ * Add anime unit test cases (port from lad1337/sickbeard) * Fix normal tv show regex (port from midgetspy/sickbeard) * Fix anime regex (port from lad1337/sickbeard) +* Add pull request checkout option to General Config/Advanced Settings [develop changelog] diff --git a/gui/slick/interfaces/default/config_general.tmpl b/gui/slick/interfaces/default/config_general.tmpl index 2817d0e0..410410c1 100644 --- a/gui/slick/interfaces/default/config_general.tmpl +++ b/gui/slick/interfaces/default/config_general.tmpl @@ -461,6 +461,24 @@ </label> </div> + #set pulls = sickbeard.versionCheckScheduler.action.list_remote_pulls() + #if len(pulls) > 0 and $sickbeard.BRANCH != 'master': + <div class="field-pair"> + <label> + <span class="component-title">Pull request:</span> + <span class="component-desc"> + <select id="pullRequestVersion" class="form-control form-control-inline input-sm pull-left"> + #for $cur_branch in $pulls: + <option value="$cur_branch.fetch_name()" #if $cur_branch == $sickbeard.BRANCH then 'selected="selected"' else ''#>$cur_branch</option> + #end for + </select> + <input class="btn btn-inline" style="margin-left: 6px;" type="button" id="pullRequestCheckout" value="Checkout Pull Request"> + <div class="clear-left"><p>select pull request to test (restart required)</p></div> + </span> + </label> + </div> + #end if + <div class="field-pair"> <label for="git_remote"> <span class="component-title">Git remote for branch</span> diff --git a/gui/slick/js/config.js b/gui/slick/js/config.js index 41046e69..06a2682b 100644 --- a/gui/slick/js/config.js +++ b/gui/slick/js/config.js @@ -113,6 +113,10 @@ $(document).ready(function(){ $('#branchCheckout').click(function(){ window.location.href = sbRoot + '/home/branchCheckout?branch=' + $('#branchVersion').val(); }); + + $('#pullRequestCheckout').click(function(){ + window.location.href = sbRoot + '/home/pullRequestCheckout?branch=' + $('#pullRequestVersion').val(); + }); }); diff --git a/sickbeard/gh_api.py b/sickbeard/gh_api.py index ef97bf44..89ed8b48 100644 --- a/sickbeard/gh_api.py +++ b/sickbeard/gh_api.py @@ -92,4 +92,27 @@ class GitHub(object): access_API = self._access_API( ['repos', self.github_repo_user, self.github_repo, 'branches'], params={'per_page': 100}) - return access_API \ No newline at end of file + return access_API + + def pull_requests(self): + access_API = self._access_API( + ['repos', self.github_repo_user, self.github_repo, 'pulls'], + params={'per_page': 100}) + pull = [] + for x in access_API: + try: + pull.append(PullRequest(x['head']['ref'], x['number'])) + except: + continue + return pull + +class PullRequest(object): + def __init__(self, ref, number): + self.ref = ref + self.number = number + + def __repr__(self): + return '%s: %s' % (self.number, self.ref) + + def fetch_name(self): + return 'pull/%s/head:pull/%s/%s' % (self.number, self.number, self.ref) \ No newline at end of file diff --git a/sickbeard/versionChecker.py b/sickbeard/versionChecker.py index 4c6d5a32..3840026c 100644 --- a/sickbeard/versionChecker.py +++ b/sickbeard/versionChecker.py @@ -115,9 +115,15 @@ class CheckVersion(): if self.updater.need_update(): return self.updater.update() + def fetch(self, pull_request): + return self.updater.fetch(pull_request) + def list_remote_branches(self): return self.updater.list_remote_branches() + def list_remote_pulls(self): + return self.updater.list_remote_pulls() + def get_branch(self): return self.updater.branch @@ -400,6 +406,17 @@ class GitUpdateManager(UpdateManager): return re.findall('\S+\Wrefs/heads/(.*)', branches) return [] + def list_remote_pulls(self): + gh = github.GitHub(self.github_repo_user, self.github_repo, self.branch) + return gh.pull_requests() + + def fetch(self, pull_request): + output, err, exit_status = self._run_git(self._git_path, 'fetch -f %s %s' % (sickbeard.GIT_REMOTE, pull_request)) # @UnusedVariable + if exit_status == 0: + return True + return False + + class SourceUpdateManager(UpdateManager): def __init__(self): @@ -596,4 +613,8 @@ class SourceUpdateManager(UpdateManager): def list_remote_branches(self): gh = github.GitHub(self.github_repo_user, self.github_repo, self.branch) - return [x['name'] for x in gh.branches() if x and 'name' in x] \ No newline at end of file + return [x['name'] for x in gh.branches() if x and 'name' in x] + + def list_remote_pulls(self): + # we don't care about testers that don't use git + return [] \ No newline at end of file diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py index e51cded0..619a1761 100644 --- a/sickbeard/webserve.py +++ b/sickbeard/webserve.py @@ -3628,6 +3628,17 @@ class Home(MainHandler): ui.notifications.message('Checking out branch: ', branch) return self.update(sickbeard.PID) + def pullRequestCheckout(self, branch): + pull_request = branch + branch = branch.split(':')[1] + fetched = sickbeard.versionCheckScheduler.action.fetch(pull_request) + if fetched: + sickbeard.BRANCH = branch + ui.notifications.message('Checking out branch: ', branch) + return self.update(sickbeard.PID) + else: + return redirect('/home/') + def displayShow(self, show=None): if show is None: From 7b969b334b09bd145af8701ceedefdc062a127d0 Mon Sep 17 00:00:00 2001 From: Adam <adam111316@users.noreply.github.com> Date: Sat, 3 Jan 2015 21:07:09 +0800 Subject: [PATCH 11/21] Fix anime searches on BTN provider --- CHANGES.md | 1 + sickbeard/providers/btn.py | 4 ---- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 4ec76cfd..a0df6e4f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -16,6 +16,7 @@ * Fix normal tv show regex (port from midgetspy/sickbeard) * Fix anime regex (port from lad1337/sickbeard) * Add pull request checkout option to General Config/Advanced Settings +* Fix anime searches on BTN provider [develop changelog] diff --git a/sickbeard/providers/btn.py b/sickbeard/providers/btn.py index 8a60192e..0a9d7049 100644 --- a/sickbeard/providers/btn.py +++ b/sickbeard/providers/btn.py @@ -201,8 +201,6 @@ class BTNProvider(generic.TorrentProvider): if ep_obj.show.air_by_date or ep_obj.show.sports: # Search for the year of the air by date show current_params['name'] = str(ep_obj.airdate).split('-')[0] - elif ep_obj.show.is_anime: - current_params['name'] = "%d" % ep_obj.scene_absolute_number else: current_params['name'] = 'Season ' + str(ep_obj.scene_season) @@ -238,8 +236,6 @@ class BTNProvider(generic.TorrentProvider): # BTN uses dots in dates, we just search for the date since that # combined with the series identifier should result in just one episode search_params['name'] = date_str.replace('-', '.') - elif ep_obj.show.anime: - search_params['name'] = "%i" % int(ep_obj.scene_absolute_number) else: # Do a general name search for the episode, formatted like SXXEYY search_params['name'] = "S%02dE%02d" % (ep_obj.scene_season, ep_obj.scene_episode) From 3c295485ee9a82b30da6262c68bcee8e8990be65 Mon Sep 17 00:00:00 2001 From: adam <adam_k_92@hotmail.com> Date: Sat, 3 Jan 2015 18:18:13 +0800 Subject: [PATCH 12/21] Add BTN api call parameter debug logging --- CHANGES.md | 2 +- sickbeard/providers/btn.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 4ec76cfd..92ca2a88 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -16,6 +16,7 @@ * Fix normal tv show regex (port from midgetspy/sickbeard) * Fix anime regex (port from lad1337/sickbeard) * Add pull request checkout option to General Config/Advanced Settings +* Add BTN api call parameter debug logging [develop changelog] @@ -65,7 +66,6 @@ * Fix normal tv show regex (port from midgetspy/sickbeard) * Fix anime regex (port from lad1337/sickbeard) - ### 0.4.0 (2014-12-04 10:50:00 UTC) * Change footer stats to not add newlines when copy/pasting from them diff --git a/sickbeard/providers/btn.py b/sickbeard/providers/btn.py index 8a60192e..5c0bae65 100644 --- a/sickbeard/providers/btn.py +++ b/sickbeard/providers/btn.py @@ -136,6 +136,8 @@ class BTNProvider(generic.TorrentProvider): server = jsonrpclib.Server(self.url) parsedJSON = {} + logger.log(u'Searching with parameters: %s' % params, logger.DEBUG) + try: parsedJSON = server.getTorrents(apikey, params, int(results_per_page), int(offset)) From c16903bd738a5522cf20c8da5d87ba8ed5678741 Mon Sep 17 00:00:00 2001 From: JackDandy <jackdandy@users.noreply.github.com> Date: Mon, 22 Dec 2014 18:30:53 +0000 Subject: [PATCH 13/21] Change "Daily" search to "Recent" search. --- CHANGES.md | 1 + .../interfaces/default/config_providers.tmpl | 30 +++--- .../interfaces/default/config_search.tmpl | 14 +-- gui/slick/interfaces/default/inc_bottom.tmpl | 2 +- .../default/manage_manageSearches.tmpl | 6 +- sickbeard/__init__.py | 102 ++++++++++-------- sickbeard/config.py | 10 +- sickbeard/providers/__init__.py | 14 +-- sickbeard/providers/generic.py | 2 +- sickbeard/providers/newznab.py | 6 +- sickbeard/providers/rsstorrent.py | 6 +- sickbeard/search.py | 4 +- .../{dailysearcher.py => searchRecent.py} | 8 +- sickbeard/search_queue.py | 22 ++-- sickbeard/tvcache.py | 4 +- sickbeard/webserve.py | 38 +++---- 16 files changed, 143 insertions(+), 126 deletions(-) rename sickbeard/{dailysearcher.py => searchRecent.py} (93%) diff --git a/CHANGES.md b/CHANGES.md index c7963fe4..c0ba8d4d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -18,6 +18,7 @@ * Add pull request checkout option to General Config/Advanced Settings * Add BTN api call parameter debug logging * Fix anime searches on BTN provider +* Change replace "Daily-Search" with "Recent-Search" [develop changelog] diff --git a/gui/slick/interfaces/default/config_providers.tmpl b/gui/slick/interfaces/default/config_providers.tmpl index 7eaccdf6..8c4c31ee 100644 --- a/gui/slick/interfaces/default/config_providers.tmpl +++ b/gui/slick/interfaces/default/config_providers.tmpl @@ -214,13 +214,13 @@ </div> #end if - #if $hasattr($curNewznabProvider, 'enable_daily'): + #if $hasattr($curNewznabProvider, 'enable_recentsearch'): <div class="field-pair"> - <label for="${curNewznabProvider.getID()}_enable_daily"> - <span class="component-title">Enable daily searches</span> + <label for="${curNewznabProvider.getID()}_enable_recentsearch"> + <span class="component-title">Enable recent searches</span> <span class="component-desc"> - <input type="checkbox" name="${curNewznabProvider.getID()}_enable_daily" id="${curNewznabProvider.getID()}_enable_daily" <%= html_checked if curNewznabProvider.enable_daily else '' %>/> - <p>perform daily searches at provider</p> + <input type="checkbox" name="${curNewznabProvider.getID()}_enable_recentsearch" id="${curNewznabProvider.getID()}_enable_recentsearch" <%= html_checked if curNewznabProvider.enable_recentsearch else '' %>/> + <p>perform recent searches at provider</p> </span> </label> </div> @@ -292,13 +292,13 @@ #end if - #if $hasattr($curNzbProvider, 'enable_daily'): + #if $hasattr($curNzbProvider, 'enable_recentsearch'): <div class="field-pair"> - <label for="${curNzbProvider.getID()}_enable_daily"> - <span class="component-title">Enable daily searches</span> + <label for="${curNzbProvider.getID()}_enable_recentsearch"> + <span class="component-title">Enable recent searches</span> <span class="component-desc"> - <input type="checkbox" name="${curNzbProvider.getID()}_enable_daily" id="${curNzbProvider.getID()}_enable_daily" <%= html_checked if curNzbProvider.enable_daily else '' %>/> - <p>enable provider to perform daily searches.</p> + <input type="checkbox" name="${curNzbProvider.getID()}_enable_recentsearch" id="${curNzbProvider.getID()}_enable_recentsearch" <%= html_checked if curNzbProvider.enable_recentsearch else '' %>/> + <p>enable provider to perform recent searches.</p> </span> </label> </div> @@ -512,13 +512,13 @@ </div> #end if - #if $hasattr($curTorrentProvider, 'enable_daily'): + #if $hasattr($curTorrentProvider, 'enable_recentsearch'): <div class="field-pair"> - <label for="${curTorrentProvider.getID()}_enable_daily"> - <span class="component-title">Enable daily searches</span> + <label for="${curTorrentProvider.getID()}_enable_recentsearch"> + <span class="component-title">Enable recent searches</span> <span class="component-desc"> - <input type="checkbox" name="${curTorrentProvider.getID()}_enable_daily" id="${curTorrentProvider.getID()}_enable_daily" <%= html_checked if curTorrentProvider.enable_daily else '' %>/> - <p>enable provider to perform daily searches.</p> + <input type="checkbox" name="${curTorrentProvider.getID()}_enable_recentsearch" id="${curTorrentProvider.getID()}_enable_recentsearch" <%= html_checked if curTorrentProvider.enable_recentsearch else '' %>/> + <p>enable provider to perform recent searches.</p> </span> </label> </div> diff --git a/gui/slick/interfaces/default/config_search.tmpl b/gui/slick/interfaces/default/config_search.tmpl index 9a4182ff..92cc1e79 100755 --- a/gui/slick/interfaces/default/config_search.tmpl +++ b/gui/slick/interfaces/default/config_search.tmpl @@ -90,10 +90,10 @@ <div class="field-pair"> <label> - <span class="component-title">Daily search frequency</span> + <span class="component-title">Recent search frequency</span> <span class="component-desc"> - <input type="text" name="dailysearch_frequency" value="$sickbeard.DAILYSEARCH_FREQUENCY" class="form-control input-sm input75" /> - <p>time in minutes between searches (min. $sickbeard.MIN_DAILYSEARCH_FREQUENCY)</p> + <input type="text" name="recentsearch_frequency" value="$sickbeard.RECENTSEARCH_FREQUENCY" class="form-control input-sm input75" /> + <p>time in minutes between searches (min. $sickbeard.MIN_RECENTSEARCH_FREQUENCY)</p> </span> </label> </div> @@ -139,11 +139,11 @@ </div> <div class="field-pair"> - <label for="dailysearch_startup"> - <span class="component-title">Daily search on startup</span> + <label for="recentsearch_startup"> + <span class="component-title">Recent search on startup</span> <span class="component-desc"> - <input type="checkbox" name="dailysearch_startup" id="dailysearch_startup" <%= html_checked if sickbeard.DAILYSEARCH_STARTUP == True else '' %>/> - <p>start daily search on startup of SickGear</p> + <input type="checkbox" name="recentsearch_startup" id="recentsearch_startup" <%= html_checked if sickbeard.RECENTSEARCH_STARTUP == True else '' %>/> + <p>start recent search on startup of SickGear</p> </span> </label> </div> diff --git a/gui/slick/interfaces/default/inc_bottom.tmpl b/gui/slick/interfaces/default/inc_bottom.tmpl index 1f1b3df5..9d8d38a8 100644 --- a/gui/slick/interfaces/default/inc_bottom.tmpl +++ b/gui/slick/interfaces/default/inc_bottom.tmpl @@ -62,7 +62,7 @@ )[0 < ep_snatched] %>  / <span class="footerhighlight">$ep_total</span> episodes downloaded - | daily search: <span class="footerhighlight"><%= str(sickbeard.dailySearchScheduler.timeLeft()).split('.')[0] %></span> + | recent search: <span class="footerhighlight"><%= str(sickbeard.recentSearchScheduler.timeLeft()).split('.')[0] %></span> | backlog search: <span class="footerhighlight">$sbdatetime.sbdatetime.sbfdate($sickbeard.backlogSearchScheduler.nextRun())</span> </div> diff --git a/gui/slick/interfaces/default/manage_manageSearches.tmpl b/gui/slick/interfaces/default/manage_manageSearches.tmpl index a3de9033..8a281b18 100644 --- a/gui/slick/interfaces/default/manage_manageSearches.tmpl +++ b/gui/slick/interfaces/default/manage_manageSearches.tmpl @@ -29,9 +29,9 @@ Currently running<br /> #end if <br /> -<h3>Daily Search:</h3> +<h3>Recent Search:</h3> <a class="btn" href="$sbRoot/manage/manageSearches/forceSearch"><i class="icon-exclamation-sign"></i> Force</a> -#if not $dailySearchStatus: +#if not $recentSearchStatus: Not in progress<br /> #else: In Progress<br /> @@ -53,7 +53,7 @@ In Progress<br /> <h3>Search Queue:</h3> Backlog: <i>$queueLength['backlog'] pending items</i></br> -Daily: <i>$queueLength['daily'] pending items</i></br> +Recent: <i>$queueLength['recent'] pending items</i></br> Manual: <i>$queueLength['manual'] pending items</i></br> Failed: <i>$queueLength['failed'] pending items</i></br> </div> diff --git a/sickbeard/__init__.py b/sickbeard/__init__.py index 8cbddb7f..bad13bc4 100755 --- a/sickbeard/__init__.py +++ b/sickbeard/__init__.py @@ -42,7 +42,7 @@ from sickbeard import searchBacklog, showUpdater, versionChecker, properFinder, from sickbeard import helpers, db, exceptions, show_queue, search_queue, scheduler, show_name_helpers from sickbeard import logger from sickbeard import naming -from sickbeard import dailysearcher +from sickbeard import searchRecent from sickbeard import scene_numbering, scene_exceptions, name_cache from indexers.indexer_api import indexerApi from indexers.indexer_exceptions import indexer_shownotfound, indexer_exception, indexer_error, indexer_episodenotfound, \ @@ -78,7 +78,7 @@ NO_RESIZE = False # system events events = None -dailySearchScheduler = None +recentSearchScheduler = None backlogSearchScheduler = None showUpdateScheduler = None versionCheckScheduler = None @@ -196,19 +196,19 @@ CHECK_PROPERS_INTERVAL = None ALLOW_HIGH_PRIORITY = False AUTOPOSTPROCESSER_FREQUENCY = None -DAILYSEARCH_FREQUENCY = None +RECENTSEARCH_FREQUENCY = None UPDATE_FREQUENCY = None -DAILYSEARCH_STARTUP = False +RECENTSEARCH_STARTUP = False BACKLOG_FREQUENCY = None BACKLOG_STARTUP = False DEFAULT_AUTOPOSTPROCESSER_FREQUENCY = 10 -DEFAULT_DAILYSEARCH_FREQUENCY = 40 +DEFAULT_RECENTSEARCH_FREQUENCY = 40 DEFAULT_BACKLOG_FREQUENCY = 21 DEFAULT_UPDATE_FREQUENCY = 1 MIN_AUTOPOSTPROCESSER_FREQUENCY = 1 -MIN_DAILYSEARCH_FREQUENCY = 10 +MIN_RECENTSEARCH_FREQUENCY = 10 MIN_BACKLOG_FREQUENCY = 10 MIN_UPDATE_FREQUENCY = 1 @@ -459,7 +459,7 @@ TRAKT_API_KEY = 'abd806c54516240c76e4ebc9c5ccf394' __INITIALIZED__ = False def get_backlog_cycle_time(): - cycletime = DAILYSEARCH_FREQUENCY * 2 + 7 + cycletime = RECENTSEARCH_FREQUENCY * 2 + 7 return max([cycletime, 720]) def initialize(consoleLogging=True): @@ -477,7 +477,7 @@ def initialize(consoleLogging=True): PLEX_SERVER_HOST, PLEX_HOST, PLEX_USERNAME, PLEX_PASSWORD, DEFAULT_BACKLOG_FREQUENCY, MIN_BACKLOG_FREQUENCY, BACKLOG_STARTUP, SKIP_REMOVED_FILES, \ showUpdateScheduler, __INITIALIZED__, LAUNCH_BROWSER, UPDATE_SHOWS_ON_START, TRASH_REMOVE_SHOW, TRASH_ROTATE_LOGS, HOME_SEARCH_FOCUS, SORT_ARTICLE, showList, loadingShowList, \ NEWZNAB_DATA, NZBS, NZBS_UID, NZBS_HASH, INDEXER_DEFAULT, INDEXER_TIMEOUT, USENET_RETENTION, TORRENT_DIR, \ - QUALITY_DEFAULT, FLATTEN_FOLDERS_DEFAULT, SUBTITLES_DEFAULT, STATUS_DEFAULT, DAILYSEARCH_STARTUP, \ + QUALITY_DEFAULT, FLATTEN_FOLDERS_DEFAULT, SUBTITLES_DEFAULT, STATUS_DEFAULT, RECENTSEARCH_STARTUP, \ GROWL_NOTIFY_ONSNATCH, GROWL_NOTIFY_ONDOWNLOAD, GROWL_NOTIFY_ONSUBTITLEDOWNLOAD, TWITTER_NOTIFY_ONSNATCH, TWITTER_NOTIFY_ONDOWNLOAD, TWITTER_NOTIFY_ONSUBTITLEDOWNLOAD, \ USE_GROWL, GROWL_HOST, GROWL_PASSWORD, USE_PROWL, PROWL_NOTIFY_ONSNATCH, PROWL_NOTIFY_ONDOWNLOAD, PROWL_NOTIFY_ONSUBTITLEDOWNLOAD, PROWL_API, PROWL_PRIORITY, PROG_DIR, \ USE_PYTIVO, PYTIVO_NOTIFY_ONSNATCH, PYTIVO_NOTIFY_ONDOWNLOAD, PYTIVO_NOTIFY_ONSUBTITLEDOWNLOAD, PYTIVO_UPDATE_LIBRARY, PYTIVO_HOST, PYTIVO_SHARE_NAME, PYTIVO_TIVO_NAME, \ @@ -485,12 +485,12 @@ def initialize(consoleLogging=True): USE_PUSHALOT, PUSHALOT_NOTIFY_ONSNATCH, PUSHALOT_NOTIFY_ONDOWNLOAD, PUSHALOT_NOTIFY_ONSUBTITLEDOWNLOAD, PUSHALOT_AUTHORIZATIONTOKEN, \ USE_PUSHBULLET, PUSHBULLET_NOTIFY_ONSNATCH, PUSHBULLET_NOTIFY_ONDOWNLOAD, PUSHBULLET_NOTIFY_ONSUBTITLEDOWNLOAD, PUSHBULLET_API, PUSHBULLET_DEVICE, \ versionCheckScheduler, VERSION_NOTIFY, AUTO_UPDATE, NOTIFY_ON_UPDATE, PROCESS_AUTOMATICALLY, UNPACK, CPU_PRESET, \ - KEEP_PROCESSED_DIR, PROCESS_METHOD, TV_DOWNLOAD_DIR, MIN_DAILYSEARCH_FREQUENCY, DEFAULT_UPDATE_FREQUENCY, MIN_UPDATE_FREQUENCY, UPDATE_FREQUENCY, \ + KEEP_PROCESSED_DIR, PROCESS_METHOD, TV_DOWNLOAD_DIR, MIN_RECENTSEARCH_FREQUENCY, DEFAULT_UPDATE_FREQUENCY, MIN_UPDATE_FREQUENCY, UPDATE_FREQUENCY, \ showQueueScheduler, searchQueueScheduler, ROOT_DIRS, CACHE_DIR, ACTUAL_CACHE_DIR, TIMEZONE_DISPLAY, \ NAMING_PATTERN, NAMING_MULTI_EP, NAMING_ANIME_MULTI_EP, NAMING_FORCE_FOLDERS, NAMING_ABD_PATTERN, NAMING_CUSTOM_ABD, NAMING_SPORTS_PATTERN, NAMING_CUSTOM_SPORTS, NAMING_ANIME_PATTERN, NAMING_CUSTOM_ANIME, NAMING_STRIP_YEAR, \ RENAME_EPISODES, AIRDATE_EPISODES, properFinderScheduler, PROVIDER_ORDER, autoPostProcesserScheduler, \ WOMBLE, OMGWTFNZBS, OMGWTFNZBS_USERNAME, OMGWTFNZBS_APIKEY, providerList, newznabProviderList, torrentRssProviderList, \ - EXTRA_SCRIPTS, USE_TWITTER, TWITTER_USERNAME, TWITTER_PASSWORD, TWITTER_PREFIX, DAILYSEARCH_FREQUENCY, \ + EXTRA_SCRIPTS, USE_TWITTER, TWITTER_USERNAME, TWITTER_PASSWORD, TWITTER_PREFIX, RECENTSEARCH_FREQUENCY, \ USE_BOXCAR, BOXCAR_USERNAME, BOXCAR_PASSWORD, BOXCAR_NOTIFY_ONDOWNLOAD, BOXCAR_NOTIFY_ONSUBTITLEDOWNLOAD, BOXCAR_NOTIFY_ONSNATCH, \ USE_BOXCAR2, BOXCAR2_ACCESSTOKEN, BOXCAR2_NOTIFY_ONDOWNLOAD, BOXCAR2_NOTIFY_ONSUBTITLEDOWNLOAD, BOXCAR2_NOTIFY_ONSNATCH, \ USE_PUSHOVER, PUSHOVER_USERKEY, PUSHOVER_APIKEY, PUSHOVER_NOTIFY_ONDOWNLOAD, PUSHOVER_NOTIFY_ONSUBTITLEDOWNLOAD, PUSHOVER_NOTIFY_ONSNATCH, \ @@ -498,7 +498,7 @@ def initialize(consoleLogging=True): USE_SYNOLOGYNOTIFIER, SYNOLOGYNOTIFIER_NOTIFY_ONSNATCH, SYNOLOGYNOTIFIER_NOTIFY_ONDOWNLOAD, SYNOLOGYNOTIFIER_NOTIFY_ONSUBTITLEDOWNLOAD, \ USE_EMAIL, EMAIL_HOST, EMAIL_PORT, EMAIL_TLS, EMAIL_USER, EMAIL_PASSWORD, EMAIL_FROM, EMAIL_NOTIFY_ONSNATCH, EMAIL_NOTIFY_ONDOWNLOAD, EMAIL_NOTIFY_ONSUBTITLEDOWNLOAD, EMAIL_LIST, \ USE_LISTVIEW, METADATA_XBMC, METADATA_XBMC_12PLUS, METADATA_MEDIABROWSER, METADATA_PS3, metadata_provider_dict, \ - NEWZBIN, NEWZBIN_USERNAME, NEWZBIN_PASSWORD, GIT_PATH, MOVE_ASSOCIATED_FILES, POSTPONE_IF_SYNC_FILES, dailySearchScheduler, NFO_RENAME, \ + NEWZBIN, NEWZBIN_USERNAME, NEWZBIN_PASSWORD, GIT_PATH, MOVE_ASSOCIATED_FILES, POSTPONE_IF_SYNC_FILES, recentSearchScheduler, NFO_RENAME, \ GUI_NAME, HOME_LAYOUT, HISTORY_LAYOUT, DISPLAY_SHOW_SPECIALS, COMING_EPS_LAYOUT, COMING_EPS_SORT, COMING_EPS_DISPLAY_PAUSED, COMING_EPS_MISSED_RANGE, FUZZY_DATING, TRIM_ZERO, DATE_PRESET, TIME_PRESET, TIME_PRESET_W_SECONDS, THEME_NAME, \ POSTER_SORTBY, POSTER_SORTDIR, \ METADATA_WDTV, METADATA_TIVO, METADATA_MEDE8ER, IGNORE_WORDS, REQUIRE_WORDS, CALENDAR_UNPROTECTED, CREATE_MISSING_SHOW_DIRS, \ @@ -674,7 +674,10 @@ def initialize(consoleLogging=True): ALLOW_HIGH_PRIORITY = bool(check_setting_int(CFG, 'General', 'allow_high_priority', 1)) - DAILYSEARCH_STARTUP = bool(check_setting_int(CFG, 'General', 'dailysearch_startup', 1)) + RECENTSEARCH_STARTUP = check_setting_int(CFG, 'General', 'dailysearch_startup', 'deprecated') + if 'deprecated' == RECENTSEARCH_STARTUP: + RECENTSEARCH_STARTUP = check_setting_int(CFG, 'General', 'recentsearch_startup', 1) + RECENTSEARCH_STARTUP = bool(RECENTSEARCH_STARTUP) BACKLOG_STARTUP = bool(check_setting_int(CFG, 'General', 'backlog_startup', 1)) SKIP_REMOVED_FILES = bool(check_setting_int(CFG, 'General', 'skip_removed_files', 0)) @@ -685,10 +688,13 @@ def initialize(consoleLogging=True): if AUTOPOSTPROCESSER_FREQUENCY < MIN_AUTOPOSTPROCESSER_FREQUENCY: AUTOPOSTPROCESSER_FREQUENCY = MIN_AUTOPOSTPROCESSER_FREQUENCY - DAILYSEARCH_FREQUENCY = check_setting_int(CFG, 'General', 'dailysearch_frequency', - DEFAULT_DAILYSEARCH_FREQUENCY) - if DAILYSEARCH_FREQUENCY < MIN_DAILYSEARCH_FREQUENCY: - DAILYSEARCH_FREQUENCY = MIN_DAILYSEARCH_FREQUENCY + RECENTSEARCH_FREQUENCY = check_setting_int(CFG, 'General', 'dailysearch_frequency', + 'deprecated') + if 'deprecated' == RECENTSEARCH_FREQUENCY: + RECENTSEARCH_FREQUENCY = check_setting_int(CFG, 'General', 'recentsearch_frequency', + DEFAULT_RECENTSEARCH_FREQUENCY) + if RECENTSEARCH_FREQUENCY < MIN_RECENTSEARCH_FREQUENCY: + RECENTSEARCH_FREQUENCY = MIN_RECENTSEARCH_FREQUENCY MIN_BACKLOG_FREQUENCY = get_backlog_cycle_time() BACKLOG_FREQUENCY = check_setting_int(CFG, 'General', 'backlog_frequency', DEFAULT_BACKLOG_FREQUENCY) @@ -1022,10 +1028,15 @@ def initialize(consoleLogging=True): curTorrentProvider.getID() + '_search_fallback', 0)) - if hasattr(curTorrentProvider, 'enable_daily'): - curTorrentProvider.enable_daily = bool(check_setting_int(CFG, curTorrentProvider.getID().upper(), - curTorrentProvider.getID() + '_enable_daily', - 1)) + if hasattr(curTorrentProvider, 'enable_recentsearch'): + curTorrentProvider.enable_recentsearch = check_setting_int(CFG, curTorrentProvider.getID().upper(), + curTorrentProvider.getID() + '_enable_dailysearch', + 'deprecated') + if 'deprecated' == curTorrentProvider.enable_recentsearch: + curTorrentProvider.enable_recentsearch = check_setting_int(CFG, curTorrentProvider.getID().upper(), + curTorrentProvider.getID() + '_enable_recentsearch', + 1) + curTorrentProvider.enable_recentsearch = bool(curTorrentProvider.enable_recentsearch) if hasattr(curTorrentProvider, 'enable_backlog'): curTorrentProvider.enable_backlog = bool(check_setting_int(CFG, curTorrentProvider.getID().upper(), @@ -1050,10 +1061,15 @@ def initialize(consoleLogging=True): curNzbProvider.search_fallback = bool(check_setting_int(CFG, curNzbProvider.getID().upper(), curNzbProvider.getID() + '_search_fallback', 0)) - if hasattr(curNzbProvider, 'enable_daily'): - curNzbProvider.enable_daily = bool(check_setting_int(CFG, curNzbProvider.getID().upper(), - curNzbProvider.getID() + '_enable_daily', - 1)) + if hasattr(curNzbProvider, 'enable_recentsearch'): + curNzbProvider.enable_recentsearch = check_setting_int(CFG, curNzbProvider.getID().upper(), + curNzbProvider.getID() + '_enable_dailysearch', + 'deprecated') + if 'deprecated' == curNzbProvider.enable_recentsearch: + curNzbProvider.enable_recentsearch = check_setting_int(CFG, curNzbProvider.getID().upper(), + curNzbProvider.getID() + '_enable_recentsearch', + 1) + curNzbProvider.enable_recentsearch = bool(curNzbProvider.enable_recentsearch) if hasattr(curNzbProvider, 'enable_backlog'): curNzbProvider.enable_backlog = bool(check_setting_int(CFG, curNzbProvider.getID().upper(), @@ -1124,11 +1140,11 @@ def initialize(consoleLogging=True): cycleTime=datetime.timedelta(seconds=3), threadName="SEARCHQUEUE") - update_interval = datetime.timedelta(minutes=DAILYSEARCH_FREQUENCY) - dailySearchScheduler = scheduler.Scheduler(dailysearcher.DailySearcher(), + update_interval = datetime.timedelta(minutes=RECENTSEARCH_FREQUENCY) + recentSearchScheduler = scheduler.Scheduler(searchRecent.RecentSearcher(), cycleTime=update_interval, - threadName="DAILYSEARCHER", - run_delay=update_now if DAILYSEARCH_STARTUP + threadName="RECENTSEARCHER", + run_delay=update_now if RECENTSEARCH_STARTUP else update_interval) update_interval = datetime.timedelta(minutes=BACKLOG_FREQUENCY) @@ -1181,15 +1197,15 @@ def start(): showUpdateScheduler, versionCheckScheduler, showQueueScheduler, \ properFinderScheduler, autoPostProcesserScheduler, searchQueueScheduler, \ subtitlesFinderScheduler, USE_SUBTITLES, traktCheckerScheduler, \ - dailySearchScheduler, events, started + recentSearchScheduler, events, started with INIT_LOCK: if __INITIALIZED__: # start sysetm events queue events.start() - # start the daily search scheduler - dailySearchScheduler.start() + # start the recent search scheduler + recentSearchScheduler.start() # start the backlog scheduler backlogSearchScheduler.start() @@ -1230,7 +1246,7 @@ def halt(): showUpdateScheduler, versionCheckScheduler, showQueueScheduler, \ properFinderScheduler, autoPostProcesserScheduler, searchQueueScheduler, \ subtitlesFinderScheduler, traktCheckerScheduler, \ - dailySearchScheduler, events, started + recentSearchScheduler, events, started with INIT_LOCK: @@ -1245,10 +1261,10 @@ def halt(): except: pass - dailySearchScheduler.stop.set() - logger.log(u"Waiting for the DAILYSEARCH thread to exit") + recentSearchScheduler.stop.set() + logger.log(u"Waiting for the RECENTSEARCH thread to exit") try: - dailySearchScheduler.join(10) + recentSearchScheduler.join(10) except: pass @@ -1397,13 +1413,13 @@ def save_config(): new_config['General']['torrent_method'] = TORRENT_METHOD new_config['General']['usenet_retention'] = int(USENET_RETENTION) new_config['General']['autopostprocesser_frequency'] = int(AUTOPOSTPROCESSER_FREQUENCY) - new_config['General']['dailysearch_frequency'] = int(DAILYSEARCH_FREQUENCY) + new_config['General']['recentsearch_frequency'] = int(RECENTSEARCH_FREQUENCY) new_config['General']['backlog_frequency'] = int(BACKLOG_FREQUENCY) new_config['General']['update_frequency'] = int(UPDATE_FREQUENCY) new_config['General']['download_propers'] = int(DOWNLOAD_PROPERS) new_config['General']['check_propers_interval'] = CHECK_PROPERS_INTERVAL new_config['General']['allow_high_priority'] = int(ALLOW_HIGH_PRIORITY) - new_config['General']['dailysearch_startup'] = int(DAILYSEARCH_STARTUP) + new_config['General']['recentsearch_startup'] = int(RECENTSEARCH_STARTUP) new_config['General']['backlog_startup'] = int(BACKLOG_STARTUP) new_config['General']['skip_removed_files'] = int(SKIP_REMOVED_FILES) new_config['General']['quality_default'] = int(QUALITY_DEFAULT) @@ -1526,9 +1542,9 @@ def save_config(): if hasattr(curTorrentProvider, 'search_fallback'): new_config[curTorrentProvider.getID().upper()][curTorrentProvider.getID() + '_search_fallback'] = int( curTorrentProvider.search_fallback) - if hasattr(curTorrentProvider, 'enable_daily'): - new_config[curTorrentProvider.getID().upper()][curTorrentProvider.getID() + '_enable_daily'] = int( - curTorrentProvider.enable_daily) + if hasattr(curTorrentProvider, 'enable_recentsearch'): + new_config[curTorrentProvider.getID().upper()][curTorrentProvider.getID() + '_enable_recentsearch'] = int( + curTorrentProvider.enable_recentsearch) if hasattr(curTorrentProvider, 'enable_backlog'): new_config[curTorrentProvider.getID().upper()][curTorrentProvider.getID() + '_enable_backlog'] = int( curTorrentProvider.enable_backlog) @@ -1550,9 +1566,9 @@ def save_config(): if hasattr(curNzbProvider, 'search_fallback'): new_config[curNzbProvider.getID().upper()][curNzbProvider.getID() + '_search_fallback'] = int( curNzbProvider.search_fallback) - if hasattr(curNzbProvider, 'enable_daily'): - new_config[curNzbProvider.getID().upper()][curNzbProvider.getID() + '_enable_daily'] = int( - curNzbProvider.enable_daily) + if hasattr(curNzbProvider, 'enable_recentsearch'): + new_config[curNzbProvider.getID().upper()][curNzbProvider.getID() + '_enable_recentsearch'] = int( + curNzbProvider.enable_recentsearch) if hasattr(curNzbProvider, 'enable_backlog'): new_config[curNzbProvider.getID().upper()][curNzbProvider.getID() + '_enable_backlog'] = int( curNzbProvider.enable_backlog) diff --git a/sickbeard/config.py b/sickbeard/config.py index f630192e..a87dabf5 100644 --- a/sickbeard/config.py +++ b/sickbeard/config.py @@ -155,13 +155,13 @@ def change_AUTOPOSTPROCESSER_FREQUENCY(freq): sickbeard.autoPostProcesserScheduler.cycleTime = datetime.timedelta(minutes=sickbeard.AUTOPOSTPROCESSER_FREQUENCY) -def change_DAILYSEARCH_FREQUENCY(freq): - sickbeard.DAILYSEARCH_FREQUENCY = to_int(freq, default=sickbeard.DEFAULT_DAILYSEARCH_FREQUENCY) +def change_RECENTSEARCH_FREQUENCY(freq): + sickbeard.RECENTSEARCH_FREQUENCY = to_int(freq, default=sickbeard.DEFAULT_RECENTSEARCH_FREQUENCY) - if sickbeard.DAILYSEARCH_FREQUENCY < sickbeard.MIN_DAILYSEARCH_FREQUENCY: - sickbeard.DAILYSEARCH_FREQUENCY = sickbeard.MIN_DAILYSEARCH_FREQUENCY + if sickbeard.RECENTSEARCH_FREQUENCY < sickbeard.MIN_RECENTSEARCH_FREQUENCY: + sickbeard.RECENTSEARCH_FREQUENCY = sickbeard.MIN_RECENTSEARCH_FREQUENCY - sickbeard.dailySearchScheduler.cycleTime = datetime.timedelta(minutes=sickbeard.DAILYSEARCH_FREQUENCY) + sickbeard.recentSearchScheduler.cycleTime = datetime.timedelta(minutes=sickbeard.RECENTSEARCH_FREQUENCY) def change_BACKLOG_FREQUENCY(freq): sickbeard.BACKLOG_FREQUENCY = to_int(freq, default=sickbeard.DEFAULT_BACKLOG_FREQUENCY) diff --git a/sickbeard/providers/__init__.py b/sickbeard/providers/__init__.py index c4e752f3..d20a101a 100755 --- a/sickbeard/providers/__init__.py +++ b/sickbeard/providers/__init__.py @@ -97,7 +97,7 @@ def getNewznabProviderList(data): providerDict[curDefault.name].needs_auth = curDefault.needs_auth providerDict[curDefault.name].search_mode = curDefault.search_mode providerDict[curDefault.name].search_fallback = curDefault.search_fallback - providerDict[curDefault.name].enable_daily = curDefault.enable_daily + providerDict[curDefault.name].enable_recentsearch = curDefault.enable_recentsearch providerDict[curDefault.name].enable_backlog = curDefault.enable_backlog return filter(lambda x: x, providerList) @@ -109,13 +109,13 @@ def makeNewznabProvider(configString): search_mode = 'eponly' search_fallback = 0 - enable_daily = 0 + enable_recentsearch = 0 enable_backlog = 0 try: values = configString.split('|') if len(values) == 9: - name, url, key, catIDs, enabled, search_mode, search_fallback, enable_daily, enable_backlog = values + name, url, key, catIDs, enabled, search_mode, search_fallback, enable_recentsearch, enable_backlog = values else: name = values[0] url = values[1] @@ -129,7 +129,7 @@ def makeNewznabProvider(configString): newznab = sys.modules['sickbeard.providers.newznab'] newProvider = newznab.NewznabProvider(name, url, key=key, catIDs=catIDs, search_mode=search_mode, - search_fallback=search_fallback, enable_daily=enable_daily, + search_fallback=search_fallback, enable_recentsearch=enable_recentsearch, enable_backlog=enable_backlog) newProvider.enabled = enabled == '1' @@ -157,13 +157,13 @@ def makeTorrentRssProvider(configString): cookies = None search_mode = 'eponly' search_fallback = 0 - enable_daily = 0 + enable_recentsearch = 0 enable_backlog = 0 try: values = configString.split('|') if len(values) == 8: - name, url, cookies, enabled, search_mode, search_fallback, enable_daily, enable_backlog = values + name, url, cookies, enabled, search_mode, search_fallback, enable_recentsearch, enable_backlog = values else: name = values[0] url = values[1] @@ -178,7 +178,7 @@ def makeTorrentRssProvider(configString): except: return - newProvider = torrentRss.TorrentRssProvider(name, url, cookies, search_mode, search_fallback, enable_daily, + newProvider = torrentRss.TorrentRssProvider(name, url, cookies, search_mode, search_fallback, enable_recentsearch, enable_backlog) newProvider.enabled = enabled == '1' diff --git a/sickbeard/providers/generic.py b/sickbeard/providers/generic.py index 46a45d32..f2a401a1 100644 --- a/sickbeard/providers/generic.py +++ b/sickbeard/providers/generic.py @@ -56,7 +56,7 @@ class GenericProvider: self.search_mode = None self.search_fallback = False - self.enable_daily = False + self.enable_recentsearch = False self.enable_backlog = False self.cache = tvcache.TVCache(self) diff --git a/sickbeard/providers/newznab.py b/sickbeard/providers/newznab.py index ebc6e827..345e2c2b 100755 --- a/sickbeard/providers/newznab.py +++ b/sickbeard/providers/newznab.py @@ -43,7 +43,7 @@ from lib.bencode import bdecode class NewznabProvider(generic.NZBProvider): def __init__(self, name, url, key='', catIDs='5030,5040', search_mode='eponly', search_fallback=False, - enable_daily=False, enable_backlog=False): + enable_recentsearch=False, enable_backlog=False): generic.NZBProvider.__init__(self, name) @@ -55,7 +55,7 @@ class NewznabProvider(generic.NZBProvider): self.search_mode = search_mode self.search_fallback = search_fallback - self.enable_daily = enable_daily + self.enable_recentsearch = enable_recentsearch self.enable_backlog = enable_backlog # a 0 in the key spot indicates that no key is needed @@ -77,7 +77,7 @@ class NewznabProvider(generic.NZBProvider): def configStr(self): return self.name + '|' + self.url + '|' + self.key + '|' + self.catIDs + '|' + str( int(self.enabled)) + '|' + self.search_mode + '|' + str(int(self.search_fallback)) + '|' + str( - int(self.enable_daily)) + '|' + str(int(self.enable_backlog)) + int(self.enable_recentsearch)) + '|' + str(int(self.enable_backlog)) def imageName(self): if ek.ek(os.path.isfile, diff --git a/sickbeard/providers/rsstorrent.py b/sickbeard/providers/rsstorrent.py index 12ca62ac..d65e33be 100644 --- a/sickbeard/providers/rsstorrent.py +++ b/sickbeard/providers/rsstorrent.py @@ -36,7 +36,7 @@ from lib.bencode import bdecode class TorrentRssProvider(generic.TorrentProvider): - def __init__(self, name, url, cookies='', search_mode='eponly', search_fallback=False, enable_daily=False, + def __init__(self, name, url, cookies='', search_mode='eponly', search_fallback=False, enable_recentsearch=False, enable_backlog=False): generic.TorrentProvider.__init__(self, name) self.cache = TorrentRssCache(self) @@ -48,7 +48,7 @@ class TorrentRssProvider(generic.TorrentProvider): self.search_mode = search_mode self.search_fallback = search_fallback - self.enable_daily = enable_daily + self.enable_recentsearch = enable_recentsearch self.enable_backlog = enable_backlog self.cookies = cookies @@ -59,7 +59,7 @@ class TorrentRssProvider(generic.TorrentProvider): self.enabled, self.search_mode or '', self.search_fallback, - self.enable_daily, + self.enable_recentsearch, self.enable_backlog) def imageName(self): diff --git a/sickbeard/search.py b/sickbeard/search.py index fcb0ee13..60948071 100644 --- a/sickbeard/search.py +++ b/sickbeard/search.py @@ -375,7 +375,7 @@ def searchForNeededEpisodes(): episodes.extend(wantedEpisodes(curShow, fromDate)) - providers = [x for x in sickbeard.providers.sortedProviderList() if x.isActive() and x.enable_daily] + providers = [x for x in sickbeard.providers.sortedProviderList() if x.isActive() and x.enable_recentsearch] for curProvider in providers: # spawn separate threads for each provider so we don't need to wait for providers with slow network operation @@ -435,7 +435,7 @@ def searchForNeededEpisodes(): if not didSearch: logger.log( - u"No NZB/Torrent providers found or enabled in the SickGear config for daily searches. Please check your settings.", + u"No NZB/Torrent providers found or enabled in the SickGear config for recent searches. Please check your settings.", logger.ERROR) return foundResults.values() diff --git a/sickbeard/dailysearcher.py b/sickbeard/searchRecent.py similarity index 93% rename from sickbeard/dailysearcher.py rename to sickbeard/searchRecent.py index d51b5422..dcaf1315 100644 --- a/sickbeard/dailysearcher.py +++ b/sickbeard/searchRecent.py @@ -32,7 +32,7 @@ from sickbeard import network_timezones from sickbeard.exceptions import ex -class DailySearcher(): +class RecentSearcher(): def __init__(self): self.lock = threading.Lock() self.amActive = False @@ -97,8 +97,8 @@ class DailySearcher(): myDB = db.DBConnection() myDB.mass_action(sql_l) - # queue episode for daily search - dailysearch_queue_item = sickbeard.search_queue.DailySearchQueueItem() - sickbeard.searchQueueScheduler.action.add_item(dailysearch_queue_item) + # queue episode for recent search + recentsearch_queue_item = sickbeard.search_queue.RecentSearchQueueItem() + sickbeard.searchQueueScheduler.action.add_item(recentsearch_queue_item) self.amActive = False \ No newline at end of file diff --git a/sickbeard/search_queue.py b/sickbeard/search_queue.py index e87ed6ec..242dc544 100644 --- a/sickbeard/search_queue.py +++ b/sickbeard/search_queue.py @@ -33,7 +33,7 @@ from sickbeard.search import pickBestResult search_queue_lock = threading.Lock() BACKLOG_SEARCH = 10 -DAILY_SEARCH = 20 +RECENT_SEARCH = 20 FAILED_SEARCH = 30 MANUAL_SEARCH = 40 @@ -95,17 +95,17 @@ class SearchQueue(generic_queue.GenericQueue): return True return False - def is_dailysearch_in_progress(self): + def is_recentsearch_in_progress(self): for cur_item in self.queue + [self.currentItem]: - if isinstance(cur_item, DailySearchQueueItem): + if isinstance(cur_item, RecentSearchQueueItem): return True return False def queue_length(self): - length = {'backlog': 0, 'daily': 0, 'manual': 0, 'failed': 0} + length = {'backlog': 0, 'recent': 0, 'manual': 0, 'failed': 0} for cur_item in self.queue: - if isinstance(cur_item, DailySearchQueueItem): - length['daily'] += 1 + if isinstance(cur_item, RecentSearchQueueItem): + length['recent'] += 1 elif isinstance(cur_item, BacklogQueueItem): length['backlog'] += 1 elif isinstance(cur_item, ManualSearchQueueItem): @@ -116,8 +116,8 @@ class SearchQueue(generic_queue.GenericQueue): def add_item(self, item): - if isinstance(item, DailySearchQueueItem): - # daily searches + if isinstance(item, RecentSearchQueueItem): + # recent searches generic_queue.GenericQueue.add_item(self, item) elif isinstance(item, BacklogQueueItem) and not self.is_in_queue(item.show, item.segment): # backlog searches @@ -128,16 +128,16 @@ class SearchQueue(generic_queue.GenericQueue): else: logger.log(u"Not adding item, it's already in the queue", logger.DEBUG) -class DailySearchQueueItem(generic_queue.QueueItem): +class RecentSearchQueueItem(generic_queue.QueueItem): def __init__(self): self.success = None - generic_queue.QueueItem.__init__(self, 'Daily Search', DAILY_SEARCH) + generic_queue.QueueItem.__init__(self, 'Recent Search', RECENT_SEARCH) def run(self): generic_queue.QueueItem.run(self) try: - logger.log("Beginning daily search for new episodes") + logger.log("Beginning recent search for new episodes") foundResults = search.searchForNeededEpisodes() if not len(foundResults): diff --git a/sickbeard/tvcache.py b/sickbeard/tvcache.py index 681ab310..a15c3c6b 100644 --- a/sickbeard/tvcache.py +++ b/sickbeard/tvcache.py @@ -97,7 +97,7 @@ class TVCache(): myDB.action('DELETE FROM [' + self.providerID + '] WHERE 1') def _get_title_and_url(self, item): - # override this in the provider if daily search has a different data layout to backlog searches + # override this in the provider if recent search has a different data layout to backlog searches return self.provider._get_title_and_url(item) def _getRSSData(self): @@ -222,7 +222,7 @@ class TVCache(): return True def shouldClearCache(self): - # if daily search hasn't used our previous results yet then don't clear the cache + # if recent search hasn't used our previous results yet then don't clear the cache if self.lastUpdate > self.lastSearch: return False diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py index 619a1761..2519e222 100644 --- a/sickbeard/webserve.py +++ b/sickbeard/webserve.py @@ -630,7 +630,7 @@ class ManageSearches(MainHandler): # t.backlogPI = sickbeard.backlogSearchScheduler.action.getProgressIndicator() t.backlogPaused = sickbeard.searchQueueScheduler.action.is_backlog_paused() # @UndefinedVariable t.backlogRunning = sickbeard.searchQueueScheduler.action.is_backlog_in_progress() # @UndefinedVariable - t.dailySearchStatus = sickbeard.dailySearchScheduler.action.amActive # @UndefinedVariable + t.recentSearchStatus = sickbeard.recentSearchScheduler.action.amActive # @UndefinedVariable t.findPropersStatus = sickbeard.properFinderScheduler.action.amActive # @UndefinedVariable t.queueLength = sickbeard.searchQueueScheduler.action.queue_length() @@ -658,10 +658,10 @@ class ManageSearches(MainHandler): def forceSearch(self, *args, **kwargs): # force it to run the next time it looks - result = sickbeard.dailySearchScheduler.forceRun() + result = sickbeard.recentSearchScheduler.forceRun() if result: - logger.log(u"Daily search forced") - ui.notifications.message('Daily search started') + logger.log(u"Recent search forced") + ui.notifications.message('Recent search started') redirect("/manage/manageSearches/") @@ -1628,10 +1628,10 @@ class ConfigSearch(MainHandler): def saveSearch(self, use_nzbs=None, use_torrents=None, nzb_dir=None, sab_username=None, sab_password=None, sab_apikey=None, sab_category=None, sab_host=None, nzbget_username=None, nzbget_password=None, nzbget_category=None, nzbget_priority=None, nzbget_host=None, nzbget_use_https=None, - backlog_days=None, backlog_frequency=None, dailysearch_frequency=None, + backlog_days=None, backlog_frequency=None, recentsearch_frequency=None, nzb_method=None, torrent_method=None, usenet_retention=None, download_propers=None, check_propers_interval=None, allow_high_priority=None, - backlog_startup=None, dailysearch_startup=None, + backlog_startup=None, recentsearch_startup=None, torrent_dir=None, torrent_username=None, torrent_password=None, torrent_host=None, torrent_label=None, torrent_path=None, torrent_verify_cert=None, torrent_seed_time=None, torrent_paused=None, torrent_high_bandwidth=None, ignore_words=None, require_words=None): @@ -1644,7 +1644,7 @@ class ConfigSearch(MainHandler): if not config.change_TORRENT_DIR(torrent_dir): results += ["Unable to create directory " + os.path.normpath(torrent_dir) + ", dir not changed."] - config.change_DAILYSEARCH_FREQUENCY(dailysearch_frequency) + config.change_RECENTSEARCH_FREQUENCY(recentsearch_frequency) config.change_BACKLOG_FREQUENCY(backlog_frequency) sickbeard.BACKLOG_DAYS = config.to_int(backlog_days, default=7) @@ -1664,7 +1664,7 @@ class ConfigSearch(MainHandler): sickbeard.ALLOW_HIGH_PRIORITY = config.checkbox_to_value(allow_high_priority) - sickbeard.DAILYSEARCH_STARTUP = config.checkbox_to_value(dailysearch_startup) + sickbeard.RECENTSEARCH_STARTUP = config.checkbox_to_value(recentsearch_startup) sickbeard.BACKLOG_STARTUP = config.checkbox_to_value(backlog_startup) sickbeard.SAB_USERNAME = sab_username @@ -2092,10 +2092,10 @@ class ConfigProviders(MainHandler): newznabProviderDict[cur_id].search_fallback = 0 try: - newznabProviderDict[cur_id].enable_daily = config.checkbox_to_value( - kwargs[cur_id + '_enable_daily']) + newznabProviderDict[cur_id].enable_recentsearch = config.checkbox_to_value( + kwargs[cur_id + '_enable_recentsearch']) except: - newznabProviderDict[cur_id].enable_daily = 0 + newznabProviderDict[cur_id].enable_recentsearch = 0 try: newznabProviderDict[cur_id].enable_backlog = config.checkbox_to_value( @@ -2258,12 +2258,12 @@ class ConfigProviders(MainHandler): except: curTorrentProvider.search_fallback = 0 # these exceptions are catching unselected checkboxes - if hasattr(curTorrentProvider, 'enable_daily'): + if hasattr(curTorrentProvider, 'enable_recentsearch'): try: - curTorrentProvider.enable_daily = config.checkbox_to_value( - kwargs[curTorrentProvider.getID() + '_enable_daily']) + curTorrentProvider.enable_recentsearch = config.checkbox_to_value( + kwargs[curTorrentProvider.getID() + '_enable_recentsearch']) except: - curTorrentProvider.enable_daily = 0 # these exceptions are actually catching unselected checkboxes + curTorrentProvider.enable_recentsearch = 0 # these exceptions are actually catching unselected checkboxes if hasattr(curTorrentProvider, 'enable_backlog'): try: @@ -2300,12 +2300,12 @@ class ConfigProviders(MainHandler): except: curNzbProvider.search_fallback = 0 # these exceptions are actually catching unselected checkboxes - if hasattr(curNzbProvider, 'enable_daily'): + if hasattr(curNzbProvider, 'enable_recentsearch'): try: - curNzbProvider.enable_daily = config.checkbox_to_value( - kwargs[curNzbProvider.getID() + '_enable_daily']) + curNzbProvider.enable_recentsearch = config.checkbox_to_value( + kwargs[curNzbProvider.getID() + '_enable_recentsearch']) except: - curNzbProvider.enable_daily = 0 # these exceptions are actually catching unselected checkboxes + curNzbProvider.enable_recentsearch = 0 # these exceptions are actually catching unselected checkboxes if hasattr(curNzbProvider, 'enable_backlog'): try: From c500a14d06f96c1e26943dc770886d070dd2bbe8 Mon Sep 17 00:00:00 2001 From: adam <adam_k_92@hotmail.com> Date: Thu, 25 Dec 2014 09:57:51 +0800 Subject: [PATCH 14/21] Add daily search to recent search renaming to config migration code --- CHANGES.md | 1 + sickbeard/__init__.py | 38 ++++++++++---------------------------- sickbeard/config.py | 20 +++++++++++++++++++- 3 files changed, 30 insertions(+), 29 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index c0ba8d4d..dc4fa000 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -19,6 +19,7 @@ * Add BTN api call parameter debug logging * Fix anime searches on BTN provider * Change replace "Daily-Search" with "Recent-Search" +* Add daily search to recent search renaming to config migration code [develop changelog] diff --git a/sickbeard/__init__.py b/sickbeard/__init__.py index bad13bc4..42204efa 100755 --- a/sickbeard/__init__.py +++ b/sickbeard/__init__.py @@ -58,7 +58,7 @@ CFG = None CONFIG_FILE = None # This is the version of the config we EXPECT to find -CONFIG_VERSION = 5 +CONFIG_VERSION = 6 # Default encryption version (0 for None) ENCRYPTION_VERSION = 0 @@ -674,10 +674,7 @@ def initialize(consoleLogging=True): ALLOW_HIGH_PRIORITY = bool(check_setting_int(CFG, 'General', 'allow_high_priority', 1)) - RECENTSEARCH_STARTUP = check_setting_int(CFG, 'General', 'dailysearch_startup', 'deprecated') - if 'deprecated' == RECENTSEARCH_STARTUP: - RECENTSEARCH_STARTUP = check_setting_int(CFG, 'General', 'recentsearch_startup', 1) - RECENTSEARCH_STARTUP = bool(RECENTSEARCH_STARTUP) + RECENTSEARCH_STARTUP = bool(check_setting_int(CFG, 'General', 'recentsearch_startup', 1)) BACKLOG_STARTUP = bool(check_setting_int(CFG, 'General', 'backlog_startup', 1)) SKIP_REMOVED_FILES = bool(check_setting_int(CFG, 'General', 'skip_removed_files', 0)) @@ -688,11 +685,8 @@ def initialize(consoleLogging=True): if AUTOPOSTPROCESSER_FREQUENCY < MIN_AUTOPOSTPROCESSER_FREQUENCY: AUTOPOSTPROCESSER_FREQUENCY = MIN_AUTOPOSTPROCESSER_FREQUENCY - RECENTSEARCH_FREQUENCY = check_setting_int(CFG, 'General', 'dailysearch_frequency', - 'deprecated') - if 'deprecated' == RECENTSEARCH_FREQUENCY: - RECENTSEARCH_FREQUENCY = check_setting_int(CFG, 'General', 'recentsearch_frequency', - DEFAULT_RECENTSEARCH_FREQUENCY) + RECENTSEARCH_FREQUENCY = check_setting_int(CFG, 'General', 'recentsearch_frequency', + DEFAULT_RECENTSEARCH_FREQUENCY) if RECENTSEARCH_FREQUENCY < MIN_RECENTSEARCH_FREQUENCY: RECENTSEARCH_FREQUENCY = MIN_RECENTSEARCH_FREQUENCY @@ -1029,15 +1023,9 @@ def initialize(consoleLogging=True): 0)) if hasattr(curTorrentProvider, 'enable_recentsearch'): - curTorrentProvider.enable_recentsearch = check_setting_int(CFG, curTorrentProvider.getID().upper(), - curTorrentProvider.getID() + '_enable_dailysearch', - 'deprecated') - if 'deprecated' == curTorrentProvider.enable_recentsearch: - curTorrentProvider.enable_recentsearch = check_setting_int(CFG, curTorrentProvider.getID().upper(), - curTorrentProvider.getID() + '_enable_recentsearch', - 1) - curTorrentProvider.enable_recentsearch = bool(curTorrentProvider.enable_recentsearch) - + curTorrentProvider.enable_recentsearch = bool(check_setting_int(CFG, curTorrentProvider.getID().upper(), + curTorrentProvider.getID() + + '_enable_recentsearch', 1)) if hasattr(curTorrentProvider, 'enable_backlog'): curTorrentProvider.enable_backlog = bool(check_setting_int(CFG, curTorrentProvider.getID().upper(), curTorrentProvider.getID() + '_enable_backlog', @@ -1062,15 +1050,9 @@ def initialize(consoleLogging=True): curNzbProvider.getID() + '_search_fallback', 0)) if hasattr(curNzbProvider, 'enable_recentsearch'): - curNzbProvider.enable_recentsearch = check_setting_int(CFG, curNzbProvider.getID().upper(), - curNzbProvider.getID() + '_enable_dailysearch', - 'deprecated') - if 'deprecated' == curNzbProvider.enable_recentsearch: - curNzbProvider.enable_recentsearch = check_setting_int(CFG, curNzbProvider.getID().upper(), - curNzbProvider.getID() + '_enable_recentsearch', - 1) - curNzbProvider.enable_recentsearch = bool(curNzbProvider.enable_recentsearch) - + curNzbProvider.enable_recentsearch = bool(check_setting_int(CFG, curNzbProvider.getID().upper(), + curNzbProvider.getID() + '_enable_recentsearch', + 1)) if hasattr(curNzbProvider, 'enable_backlog'): curNzbProvider.enable_backlog = bool(check_setting_int(CFG, curNzbProvider.getID().upper(), curNzbProvider.getID() + '_enable_backlog', diff --git a/sickbeard/config.py b/sickbeard/config.py index a87dabf5..bcbfc025 100644 --- a/sickbeard/config.py +++ b/sickbeard/config.py @@ -27,6 +27,8 @@ from sickbeard import helpers from sickbeard import logger from sickbeard import naming from sickbeard import db +from sickbeard import providers +from sickbeard.providers.generic import GenericProvider naming_ep_type = ("%(seasonnumber)dx%(episodenumber)02d", "s%(seasonnumber)02de%(episodenumber)02d", @@ -445,7 +447,8 @@ class ConfigMigrator(): 2: 'Sync backup number with version number', 3: 'Rename omgwtfnzb variables', 4: 'Add newznab catIDs', - 5: 'Metadata update' + 5: 'Metadata update', + 6: 'Rename daily search to recent search' } def migrate_config(self): @@ -712,3 +715,18 @@ class ConfigMigrator(): sickbeard.METADATA_WDTV = _migrate_metadata(metadata_wdtv, 'WDTV', use_banner) sickbeard.METADATA_TIVO = _migrate_metadata(metadata_tivo, 'TIVO', use_banner) sickbeard.METADATA_MEDE8ER = _migrate_metadata(metadata_mede8er, 'Mede8er', use_banner) + + # Migration v6: Rename daily search to recent search + def _migrate_v6(self): + + sickbeard.RECENTSEARCH_FREQUENCY = check_setting_int(self.config_obj, 'General', 'dailysearch_frequency', + sickbeard.DEFAULT_RECENTSEARCH_FREQUENCY) + + sickbeard.RECENTSEARCH_STARTUP = bool(check_setting_int(self.config_obj, 'General', 'dailysearch_startup', 1)) + if sickbeard.RECENTSEARCH_FREQUENCY < sickbeard.MIN_RECENTSEARCH_FREQUENCY: + sickbeard.RECENTSEARCH_FREQUENCY = sickbeard.MIN_RECENTSEARCH_FREQUENCY + + for curProvider in providers.sortedProviderList(): + if hasattr(curProvider, 'enable_recentsearch'): + curProvider.enable_recentsearch = bool(check_setting_int(self.config_obj, curProvider.getID().upper(), + curProvider.getID() + '_enable_dailysearch', 1)) \ No newline at end of file From 97ade1d6213bef69c469425d18006f1e712f649b Mon Sep 17 00:00:00 2001 From: Supremicus <Supremicus@users.noreply.github.com> Date: Tue, 2 Dec 2014 17:12:56 +1000 Subject: [PATCH 15/21] Change Calendar layout on the Coming Episodes page. Change view to a fluid layout. Change episode layout design. Add day and month to column headers. Add isotope plug-in to enable sort columns by Date, Network, and Show name. Add imagesLoaded plug-in to prevent layout breakage by calling isotope to update content after a page auto-refresh. --- CHANGES.md | 3 + gui/slick/css/dark.css | 25 ++- gui/slick/css/light.css | 29 +++- gui/slick/css/style.css | 99 ++++++++---- .../interfaces/default/comingEpisodes.tmpl | 153 +++++++++++++----- gui/slick/interfaces/default/inc_top.tmpl | 1 + gui/slick/js/lib/imagesloaded.pkgd.min.js | 7 + 7 files changed, 238 insertions(+), 79 deletions(-) create mode 100644 gui/slick/js/lib/imagesloaded.pkgd.min.js diff --git a/CHANGES.md b/CHANGES.md index dc4fa000..ebe7c185 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -20,6 +20,9 @@ * Fix anime searches on BTN provider * Change replace "Daily-Search" with "Recent-Search" * Add daily search to recent search renaming to config migration code +* Change Coming Episodes calendar view to a fluid layout, change episode layout design, and add day and month in column headers. +* Add isotope plug-in to Coming Episodes calendar view to enable sort columns by Date, Network, and Show name. +* Add imagesLoaded plug-in to prevent layout breakage by calling isotope to update content after a page auto-refresh. [develop changelog] diff --git a/gui/slick/css/dark.css b/gui/slick/css/dark.css index 01402916..3a7d45dc 100644 --- a/gui/slick/css/dark.css +++ b/gui/slick/css/dark.css @@ -1325,17 +1325,30 @@ h2.day, h2.network { color: #09A2FF; } -table.cal-odd { +.calendar-row .day-number { + background-color: #15528F; + color: #fff; +} + +.today .day-number .number, .today .day-number .month, .today .day-number .day { + color: #8dbeee; +} + +.odd .calendar-show { background-color: #333; } -table.cal-even { + +.even .calendar-show { background-color: #3d3d3d; } -.calendarShow .text .airtime { - color:#fff + +.calendar-row .poster img { + border: 1px solid #111; } -.calendarShow .text .episode-title { - color:#aaa + +.calendar-row .text .airtime, +.calendar-row .text .episode-title { + color: #fff; } /* ======================================================================= diff --git a/gui/slick/css/light.css b/gui/slick/css/light.css index b5b79722..fc2dd64d 100644 --- a/gui/slick/css/light.css +++ b/gui/slick/css/light.css @@ -1307,17 +1307,30 @@ h2.day, h2.network { vertical-align: middle; } -table.cal-odd { - background-color: #ddd; +.calendar-row .day-number { + background-color: #333; + color: #fff; } -table.cal-even { - background-color: #d2d2d2; + +.today .day-number .number, .today .day-number .month, .today .day-number .day { + color: #c7db40; } -.calendarShow .text .airtime { - color:#000 + +.odd .calendar-show { + background-color: #F5F1E4; } -.calendarShow .text .episode-title { - color:#888 + +.even .calendar-show { + background-color: #DFDACF; +} + +.calendar-row .poster img { + border: 1px solid #CCC; +} + +.calendar-row .text .airtime, +.calendar-row .text .episode-title { + color: #000; } /* ======================================================================= diff --git a/gui/slick/css/style.css b/gui/slick/css/style.css index bd02c682..53dbb1c9 100644 --- a/gui/slick/css/style.css +++ b/gui/slick/css/style.css @@ -1498,45 +1498,90 @@ h2.day, h2.network { } .calendarWrapper { - width:1000px; - margin:0 auto; - padding:0 3px + max-width: 1400px; + margin: 0 auto; + padding: 0 3px } -.calendarTable { - float:left; - width:142px !important; - white-space:nowrap; - table-layout:fixed !important; +.calendar-row { + float: left; + width: 14.28%; + padding: 0px 2px; } -.calendarShow { - padding:0 !important +.calendar-row .day-number { + position: relative; + height: 40px; + background-color: #333; + color: #fff; } -.calendarShow .poster { - padding-bottom:2px -} -.calendarShow .poster img { - width:142px; - height:auto +.calendar-row .day-number .number { + position: absolute; + right: 5px; + font-weight: bold; + font-size: 32px; + line-height: 38px; } -.calendarShow .text { - padding:0 5px 10px 5px +.calendar-row .day-number .day { + position: absolute; + left: 5px; + top: 3px; + text-transform: uppercase; + font-weight: bold; } -.calendarShow .text .airtime, -.calendarShow .text .episode-title { - overflow:hidden; - text-overflow:ellipsis; - display:block; - font-size:11px +.calendar-row .day-number .month { + position: absolute; + left: 5px; + bottom: 3px; + text-transform: uppercase; } -.calendarShow .show-status { - padding:5px 10px 10px; - text-align:center +.today .day-number .number, .today .day-number .month, .today .day-number .day { + color: #c7db40; +} + +.calendar-show { + margin-top: 4px; + padding: 4px; + width: 100% +} + +.odd .calendar-show { + background-color: #F5F1E4; +} + +.even .calendar-show { + background-color: #DFDACF; +} + +.calendar-row .poster img { + border: 1px solid #CCC; + border-radius: 5px; + margin-bottom: 2px; + display: block; + margin-left: auto; + margin-right: auto; +} + +.calendar-row .text .airtime, +.calendar-row .text .episode-title { + overflow: hidden; + text-overflow: ellipsis; + display: block; + font-size: 12px; +} + +.calendar-row .episode-blank { + width: 250px; + height: 32px; + text-align: center; + font-style: italic; + display: table-cell; + vertical-align: middle; + font-size: 12px; } /* ======================================================================= diff --git a/gui/slick/interfaces/default/comingEpisodes.tmpl b/gui/slick/interfaces/default/comingEpisodes.tmpl index 9e012219..f10003b4 100644 --- a/gui/slick/interfaces/default/comingEpisodes.tmpl +++ b/gui/slick/interfaces/default/comingEpisodes.tmpl @@ -20,6 +20,54 @@ <h1 class="title">$title</h1> #end if +<script type="text/javascript" charset="utf-8"> +<!-- +\$(document).ready(function(){ + + var \$container = [\$('#day0'), \$('#day1'), \$('#day2'), \$('#day3'), \$('#day4'), \$('#day5'), \$('#day6')]; + + jQuery.each(\$container, function (j) { + this.isotope({ + itemSelector: '.calendar-show', + sortBy : '$sickbeard.COMING_EPS_SORT', + layoutMode: 'vertical', + transitionDuration: 0, + getSortData: { + show: function( itemElem ) { + var name = \$( itemElem ).attr('data-name'); + #if not $sickbeard.SORT_ARTICLE: + return (name || '').replace(/^(?:(?:A(?!\s+to)n?)|The)\s(\w)/i, '$1'); + #else: + return (name || ''); + #end if + }, + network: '[data-network]', + date: function( itemElem ) { + var date = \$( itemElem ).attr('data-date'); + return date.length && parseInt( date, 10 ); + } + } + }); + }); + + imagesLoaded( '.calendar-show', function() { + jQuery.each(\$container, function (j) { + this.isotope('layout'); + }); + }); + + \$('#sort').on( 'change', function() { + var sortValue = this.value; + jQuery.each(\$container, function (j) { + this.isotope({ sortBy: sortValue }); + }); + \$.get(this.options[this.selectedIndex].getAttribute('data-sort')); + }); + +}); +//--> +</script> + <style type="text/css"> #SubMenu {display:none} #contentWrapper {padding-top:30px} @@ -35,7 +83,7 @@ </select> </span>   - +#if 'calendar' != $layout: <span>Sort By: <select name="sort" class="form-control form-control-inline input-sm" onchange="location = this.options[this.selectedIndex].value;"> <option value="$sbRoot/setComingEpsSort/?sort=date" #if 'date' == $sickbeard.COMING_EPS_SORT then 'selected="selected"' else ''#>Date</option> @@ -44,7 +92,16 @@ </select> </span>   - +#else + <span>Sort By: + <select name="sort" id="sort" class="form-control form-control-inline input-sm"> + <option value="date" data-sort="$sbRoot/setComingEpsSort/?sort=date" #if 'date' == $sickbeard.COMING_EPS_SORT then 'selected="selected"' else ''#>Date</option> + <option value="network" data-sort="$sbRoot/setComingEpsSort/?sort=network" #if 'network' == $sickbeard.COMING_EPS_SORT then 'selected="selected"' else ''#>Network</option> + <option value="show" data-sort="$sbRoot/setComingEpsSort/?sort=show" #if 'show' == $sickbeard.COMING_EPS_SORT then 'selected="selected"' else ''#>Show</option> + </select> + </span> +   +#end if <span>View Paused: <select name="viewpaused" class="form-control form-control-inline input-sm" onchange="location = this.options[this.selectedIndex].value;"> <option value="$sbRoot/toggleComingEpsDisplayPaused"<%= (' selected="selected"', '')[True == sickbeard.COMING_EPS_DISPLAY_PAUSED] %>>Hidden</option> @@ -489,53 +546,73 @@ <input type="hidden" id="sbRoot" value="$sbRoot" /> #for $day in $dates #set $tbl_day += 1 - <table class="sickbeardTable tablesorter calendarTable <%= 'cal-%s' % (('even', 'odd')[1 == tbl_day % 2]) %>" cellspacing="0" border="0" cellpadding="0"> - <thead><tr><th>$sbdatetime.sbdatetime.sbfdate($day, '%A').decode($sickbeard.SYS_ENCODING).capitalize()</th></tr></thead> - <tbody> - #set $day_has_show = False - #for $cur_result in $sql_results: - #if int($cur_result['paused']) and not $sickbeard.COMING_EPS_DISPLAY_PAUSED: - #continue - #end if - #set $cur_indexer = int($cur_result['indexer']) - #set $runtime = $cur_result['runtime'] - #set $airday = $cur_result['localtime'].date() + #if $tbl_day == 1 + #set $showtoday = 'today' + #else + #set $showtoday = '' + #end if - #if $airday == $day: - #set $day_has_show = True - #set $airtime = $sbdatetime.sbdatetime.sbftime($cur_result['localtime']).decode($sickbeard.SYS_ENCODING) - #if $sickbeard.TRIM_ZERO: - #set $airtime = re.sub(r'0(\d:\d\d)', r'\1', $airtime, 0, re.IGNORECASE | re.MULTILINE) - #end if + <div class="calendar-row $showtoday <%= '%s' % (('even', 'odd')[1 == tbl_day % 2]) %>"> + <div class="day-number"> + <div class="number">$sbdatetime.sbdatetime.sbfdate($day, ' %d').decode($sickbeard.SYS_ENCODING).replace(' 0', ' ')</div> + <div class="day"> + <span class="visible-lg">$sbdatetime.sbdatetime.sbfdate($day, '%A').decode($sickbeard.SYS_ENCODING).capitalize()</span> + <span class="hidden-lg">$sbdatetime.sbdatetime.sbfdate($day, '%a').decode($sickbeard.SYS_ENCODING).capitalize()</span> + </div> + <div class="month"> + <span class="visible-lg">$sbdatetime.sbdatetime.sbfdate($day, '%B').decode($sickbeard.SYS_ENCODING).capitalize()</span> + <span class="hidden-lg">$sbdatetime.sbdatetime.sbfdate($day, '%b').decode($sickbeard.SYS_ENCODING).capitalize()</span> + </div> + </div> + <div id="$sbdatetime.sbdatetime.sbfdate($day, 'day%w')"> + + #set $day_has_show = False + #for $cur_result in $sql_results: + #if int($cur_result['paused']) and not $sickbeard.COMING_EPS_DISPLAY_PAUSED: + #continue + #end if - <tr> - <td class="calendarShow"> - <div class="poster"> - <a title="${cur_result['show_name']}" href="$sbRoot/home/displayShow?show=${cur_result['showid']}"><img alt="" src="$sbRoot/showPoster/?show=${cur_result['showid']}&which=poster_thumb" /></a> + #set $cur_indexer = int($cur_result['indexer']) + #set $runtime = $cur_result['runtime'] + #set $airday = $cur_result['localtime'].date() + + #if $airday == $day: + #set $day_has_show = True + #set $airtime = $sbdatetime.sbdatetime.sbftime($cur_result['localtime']).decode($sickbeard.SYS_ENCODING) + + #if $sickbeard.TRIM_ZERO: + #set $airtime = re.sub(r'0(\d:\d\d)', r'\1', $airtime, 0, re.IGNORECASE | re.MULTILINE) + #end if + + <div id="show-$cur_result['showid']" class="calendar-show" data-name="$cur_result['show_name']" data-network="$cur_result['network']" data-date="$time.mktime($cur_result['localtime'].timetuple())"> + <div class="poster"> + <a title="${cur_result['show_name']}" href="$sbRoot/home/displayShow?show=${cur_result['showid']}"><img class="img-responsive" alt="" src="$sbRoot/showPoster/?show=${cur_result['showid']}&which=poster_thumb" /></a> + </div> + <div class="text"> + <div class="episode-title" title="$cur_result['name']"> + <%= 'S%02iE%02i' % (int(cur_result['season']), int(cur_result['episode'])) %> - $cur_result['name'] </div> - <div class="text"> - <span class="airtime"> - ${airtime} on $cur_result["network"] - </span> - <span class="episode-title" title="$cur_result['name']"> - <%= 'S%02iE%02i' % (int(cur_result['season']), int(cur_result['episode'])) %> - $cur_result['name'] - </span> + <div class="airtime"> + ${airtime} on $cur_result["network"] </div> - </td> <!-- end $cur_result['show_name'] --> - </tr> + </div> + </div><!-- end show-$cur_result['showid'] //--> + #end if #end for #if not $day_has_show: - <tr><td class="calendarShow"><span class="show-status">No shows for this day</span></td></tr> - #end if - </tbody> - </table> - #end for + + <div class="calendar-show" data-date="0"> + <span class="episode-blank">No shows for this day</span> + </div> + #end if + </div> + </div> + #end for <!-- end calender view //--> -</div> #end if <div class="clearfix"></div> diff --git a/gui/slick/interfaces/default/inc_top.tmpl b/gui/slick/interfaces/default/inc_top.tmpl index 1c9297b2..e854d60f 100644 --- a/gui/slick/interfaces/default/inc_top.tmpl +++ b/gui/slick/interfaces/default/inc_top.tmpl @@ -57,6 +57,7 @@ <script type="text/javascript" src="$sbRoot/js/lib/jquery.form-3.35.js?$sbPID"></script> <script type="text/javascript" src="$sbRoot/js/lib/jquery.ui.touch-punch-0.2.2.min.js?$sbPID"></script> <script type="text/javascript" src="$sbRoot/js/lib/isotope.pkgd.min.js?$sbPID"></script> + <script type="text/javascript" src="$sbRoot/js/lib/imagesloaded.pkgd.min.js?$sbPID"></script> <script type="text/javascript" src="$sbRoot/js/lib/jquery.confirm.js?$sbPID"></script> <script type="text/javascript" src="$sbRoot/js/script.js?$sbPID"></script> diff --git a/gui/slick/js/lib/imagesloaded.pkgd.min.js b/gui/slick/js/lib/imagesloaded.pkgd.min.js new file mode 100644 index 00000000..d66f6589 --- /dev/null +++ b/gui/slick/js/lib/imagesloaded.pkgd.min.js @@ -0,0 +1,7 @@ +/*! + * imagesLoaded PACKAGED v3.1.8 + * JavaScript is all like "You images are done yet or what?" + * MIT License + */ + +(function(){function e(){}function t(e,t){for(var n=e.length;n--;)if(e[n].listener===t)return n;return-1}function n(e){return function(){return this[e].apply(this,arguments)}}var i=e.prototype,r=this,o=r.EventEmitter;i.getListeners=function(e){var t,n,i=this._getEvents();if("object"==typeof e){t={};for(n in i)i.hasOwnProperty(n)&&e.test(n)&&(t[n]=i[n])}else t=i[e]||(i[e]=[]);return t},i.flattenListeners=function(e){var t,n=[];for(t=0;e.length>t;t+=1)n.push(e[t].listener);return n},i.getListenersAsObject=function(e){var t,n=this.getListeners(e);return n instanceof Array&&(t={},t[e]=n),t||n},i.addListener=function(e,n){var i,r=this.getListenersAsObject(e),o="object"==typeof n;for(i in r)r.hasOwnProperty(i)&&-1===t(r[i],n)&&r[i].push(o?n:{listener:n,once:!1});return this},i.on=n("addListener"),i.addOnceListener=function(e,t){return this.addListener(e,{listener:t,once:!0})},i.once=n("addOnceListener"),i.defineEvent=function(e){return this.getListeners(e),this},i.defineEvents=function(e){for(var t=0;e.length>t;t+=1)this.defineEvent(e[t]);return this},i.removeListener=function(e,n){var i,r,o=this.getListenersAsObject(e);for(r in o)o.hasOwnProperty(r)&&(i=t(o[r],n),-1!==i&&o[r].splice(i,1));return this},i.off=n("removeListener"),i.addListeners=function(e,t){return this.manipulateListeners(!1,e,t)},i.removeListeners=function(e,t){return this.manipulateListeners(!0,e,t)},i.manipulateListeners=function(e,t,n){var i,r,o=e?this.removeListener:this.addListener,s=e?this.removeListeners:this.addListeners;if("object"!=typeof t||t instanceof RegExp)for(i=n.length;i--;)o.call(this,t,n[i]);else for(i in t)t.hasOwnProperty(i)&&(r=t[i])&&("function"==typeof r?o.call(this,i,r):s.call(this,i,r));return this},i.removeEvent=function(e){var t,n=typeof e,i=this._getEvents();if("string"===n)delete i[e];else if("object"===n)for(t in i)i.hasOwnProperty(t)&&e.test(t)&&delete i[t];else delete this._events;return this},i.removeAllListeners=n("removeEvent"),i.emitEvent=function(e,t){var n,i,r,o,s=this.getListenersAsObject(e);for(r in s)if(s.hasOwnProperty(r))for(i=s[r].length;i--;)n=s[r][i],n.once===!0&&this.removeListener(e,n.listener),o=n.listener.apply(this,t||[]),o===this._getOnceReturnValue()&&this.removeListener(e,n.listener);return this},i.trigger=n("emitEvent"),i.emit=function(e){var t=Array.prototype.slice.call(arguments,1);return this.emitEvent(e,t)},i.setOnceReturnValue=function(e){return this._onceReturnValue=e,this},i._getOnceReturnValue=function(){return this.hasOwnProperty("_onceReturnValue")?this._onceReturnValue:!0},i._getEvents=function(){return this._events||(this._events={})},e.noConflict=function(){return r.EventEmitter=o,e},"function"==typeof define&&define.amd?define("eventEmitter/EventEmitter",[],function(){return e}):"object"==typeof module&&module.exports?module.exports=e:this.EventEmitter=e}).call(this),function(e){function t(t){var n=e.event;return n.target=n.target||n.srcElement||t,n}var n=document.documentElement,i=function(){};n.addEventListener?i=function(e,t,n){e.addEventListener(t,n,!1)}:n.attachEvent&&(i=function(e,n,i){e[n+i]=i.handleEvent?function(){var n=t(e);i.handleEvent.call(i,n)}:function(){var n=t(e);i.call(e,n)},e.attachEvent("on"+n,e[n+i])});var r=function(){};n.removeEventListener?r=function(e,t,n){e.removeEventListener(t,n,!1)}:n.detachEvent&&(r=function(e,t,n){e.detachEvent("on"+t,e[t+n]);try{delete e[t+n]}catch(i){e[t+n]=void 0}});var o={bind:i,unbind:r};"function"==typeof define&&define.amd?define("eventie/eventie",o):e.eventie=o}(this),function(e,t){"function"==typeof define&&define.amd?define(["eventEmitter/EventEmitter","eventie/eventie"],function(n,i){return t(e,n,i)}):"object"==typeof exports?module.exports=t(e,require("wolfy87-eventemitter"),require("eventie")):e.imagesLoaded=t(e,e.EventEmitter,e.eventie)}(window,function(e,t,n){function i(e,t){for(var n in t)e[n]=t[n];return e}function r(e){return"[object Array]"===d.call(e)}function o(e){var t=[];if(r(e))t=e;else if("number"==typeof e.length)for(var n=0,i=e.length;i>n;n++)t.push(e[n]);else t.push(e);return t}function s(e,t,n){if(!(this instanceof s))return new s(e,t);"string"==typeof e&&(e=document.querySelectorAll(e)),this.elements=o(e),this.options=i({},this.options),"function"==typeof t?n=t:i(this.options,t),n&&this.on("always",n),this.getImages(),a&&(this.jqDeferred=new a.Deferred);var r=this;setTimeout(function(){r.check()})}function f(e){this.img=e}function c(e){this.src=e,v[e]=this}var a=e.jQuery,u=e.console,h=u!==void 0,d=Object.prototype.toString;s.prototype=new t,s.prototype.options={},s.prototype.getImages=function(){this.images=[];for(var e=0,t=this.elements.length;t>e;e++){var n=this.elements[e];"IMG"===n.nodeName&&this.addImage(n);var i=n.nodeType;if(i&&(1===i||9===i||11===i))for(var r=n.querySelectorAll("img"),o=0,s=r.length;s>o;o++){var f=r[o];this.addImage(f)}}},s.prototype.addImage=function(e){var t=new f(e);this.images.push(t)},s.prototype.check=function(){function e(e,r){return t.options.debug&&h&&u.log("confirm",e,r),t.progress(e),n++,n===i&&t.complete(),!0}var t=this,n=0,i=this.images.length;if(this.hasAnyBroken=!1,!i)return this.complete(),void 0;for(var r=0;i>r;r++){var o=this.images[r];o.on("confirm",e),o.check()}},s.prototype.progress=function(e){this.hasAnyBroken=this.hasAnyBroken||!e.isLoaded;var t=this;setTimeout(function(){t.emit("progress",t,e),t.jqDeferred&&t.jqDeferred.notify&&t.jqDeferred.notify(t,e)})},s.prototype.complete=function(){var e=this.hasAnyBroken?"fail":"done";this.isComplete=!0;var t=this;setTimeout(function(){if(t.emit(e,t),t.emit("always",t),t.jqDeferred){var n=t.hasAnyBroken?"reject":"resolve";t.jqDeferred[n](t)}})},a&&(a.fn.imagesLoaded=function(e,t){var n=new s(this,e,t);return n.jqDeferred.promise(a(this))}),f.prototype=new t,f.prototype.check=function(){var e=v[this.img.src]||new c(this.img.src);if(e.isConfirmed)return this.confirm(e.isLoaded,"cached was confirmed"),void 0;if(this.img.complete&&void 0!==this.img.naturalWidth)return this.confirm(0!==this.img.naturalWidth,"naturalWidth"),void 0;var t=this;e.on("confirm",function(e,n){return t.confirm(e.isLoaded,n),!0}),e.check()},f.prototype.confirm=function(e,t){this.isLoaded=e,this.emit("confirm",this,t)};var v={};return c.prototype=new t,c.prototype.check=function(){if(!this.isChecked){var e=new Image;n.bind(e,"load",this),n.bind(e,"error",this),e.src=this.src,this.isChecked=!0}},c.prototype.handleEvent=function(e){var t="on"+e.type;this[t]&&this[t](e)},c.prototype.onload=function(e){this.confirm(!0,"onload"),this.unbindProxyEvents(e)},c.prototype.onerror=function(e){this.confirm(!1,"onerror"),this.unbindProxyEvents(e)},c.prototype.confirm=function(e,t){this.isConfirmed=!0,this.isLoaded=e,this.emit("confirm",this,t)},c.prototype.unbindProxyEvents=function(e){n.unbind(e.target,"load",this),n.unbind(e.target,"error",this)},s}); \ No newline at end of file From ccb9bb329ce32c5955f0962a9bcc65373170d691 Mon Sep 17 00:00:00 2001 From: JackDandy <jackdandy@users.noreply.github.com> Date: Tue, 16 Dec 2014 14:14:54 +0000 Subject: [PATCH 16/21] Coming Episodes Overhaul. Change Coming Episodes to "Episodes" page (API endpoint is not renamed). Add coming episodes to episode view renaming to config migration code. Change Layout term "Calender" to "Day by Day" on Episodes page. Fix saving of sort modes to config file on Episodes page. Add qTip episode plots to "Day by Day" on Episodes page. Add article sorting to networks on Episodes page. Add toggle sort direction and multidimensional sort to isotope on Episodes page. Add text "[paused]" where appropriate to shows on layout Day by Day. Simplified sort code in webserver and in template. Change page auto refresh from 10 to 30 mins. Add other UI tweaks. --- CHANGES.md | 18 +- gui/slick/css/dark.css | 399 +++++----- gui/slick/css/light.css | 205 +++--- gui/slick/css/style.css | 240 +++--- gui/slick/interfaces/default/apiBuilder.tmpl | 4 +- .../interfaces/default/comingEpisodes.tmpl | 626 ---------------- .../interfaces/default/config_general.tmpl | 2 +- gui/slick/interfaces/default/episodeView.tmpl | 695 ++++++++++++++++++ .../default/home_trendingShows.tmpl | 2 +- gui/slick/interfaces/default/inc_top.tmpl | 6 +- gui/slick/js/plotTooltip.js | 2 +- sickbeard/__init__.py | 28 +- sickbeard/config.py | 16 +- sickbeard/webapi.py | 40 +- sickbeard/webserve.py | 101 ++- 15 files changed, 1233 insertions(+), 1151 deletions(-) delete mode 100644 gui/slick/interfaces/default/comingEpisodes.tmpl create mode 100644 gui/slick/interfaces/default/episodeView.tmpl diff --git a/CHANGES.md b/CHANGES.md index ebe7c185..6adf19de 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,4 +1,4 @@ -### 0.x.x (2014-12-xx xx:xx:xx UTC) +### 0.x.x (2015-01-xx xx:xx:xx UTC) * Add network logos BBC Canada, Crackle, El Rey Network, SKY Atlantic, and Watch * Change Yahoo! screen network logo @@ -20,9 +20,19 @@ * Fix anime searches on BTN provider * Change replace "Daily-Search" with "Recent-Search" * Add daily search to recent search renaming to config migration code -* Change Coming Episodes calendar view to a fluid layout, change episode layout design, and add day and month in column headers. -* Add isotope plug-in to Coming Episodes calendar view to enable sort columns by Date, Network, and Show name. -* Add imagesLoaded plug-in to prevent layout breakage by calling isotope to update content after a page auto-refresh. +* Change Coming Episodes calendar view to a fluid layout, change episode layout design, and add day and month in column headers +* Add isotope plug-in to Coming Episodes calendar view to enable sort columns by Date, Network, and Show name +* Add imagesLoaded plug-in to prevent layout breakage by calling isotope to update content after a page auto-refresh +* Change Coming Episodes to "Episodes" page (API endpoint is not renamed) +* Add coming episodes to episode view renaming to config migration code +* Change Layout term "Calender" to "Day by Day" on Episodes page +* Fix saving of sort modes to config file on Episodes page +* Add qTip episode plots to "Day by Day" on Episodes page +* Add article sorting to networks on Episodes page +* Add toggle sort direction and multidimensional sort to isotope on Episodes page +* Add text "[paused]" where appropriate to shows on layout Day by Day on Episodes page +* Change Epsiodes page auto refresh from 10 to 30 mins +* Add UI tweaks [develop changelog] diff --git a/gui/slick/css/dark.css b/gui/slick/css/dark.css index 3a7d45dc..7a0083ad 100644 --- a/gui/slick/css/dark.css +++ b/gui/slick/css/dark.css @@ -149,22 +149,18 @@ inc_top.tmpl margin-bottom: -15px; } -#contentWrapper { -/* background: url("../images/bg.png") repeat 0 0 transparent; */ +[class^="icon-"], +[class*=" icon-"] { + background-image: url("../images/glyphicons-halflings.png"); } -[class^="icon-"], -[class*=" icon-"] { - background-image: url("../images/glyphicons-halflings.png"); +.icon-white { + background-image: url("../images/glyphicons-halflings-white.png"); } -.icon-white { - background-image: url("../images/glyphicons-halflings-white.png"); -} - -.dropdown-menu li > a:hover > [class^="menu-icon-"], -.dropdown-menu li > a:hover > [class*=" menu-icon-"] { - background-image: url("../images/menu/menu-icons-white.png"); +.dropdown-menu li > a:hover > [class^="menu-icon-"], +.dropdown-menu li > a:hover > [class*=" menu-icon-"] { + background-image: url("../images/menu/menu-icons-white.png"); } .infoTableHeader .icon16-sb { @@ -172,29 +168,29 @@ inc_top.tmpl } .ui-autocomplete-loading { - background: white url("../images/loading16.gif") right center no-repeat; + background: white url("../images/loading16.gif") right center no-repeat; } -.browserDialog.busy .ui-dialog-buttonpane { - background: url("../images/loading.gif") 10px 50% no-repeat !important; +.browserDialog.busy .ui-dialog-buttonpane { + background: url("../images/loading.gif") 10px 50% no-repeat !important; } -.ui-progressbar .ui-progressbar-overlay { - background: url("../css/lib/images/animated-overlay.gif"); +.ui-progressbar .ui-progressbar-overlay { + background: url("../css/lib/images/animated-overlay.gif"); } -.ui-dialog, -.ui-dialog-buttonpane { - background: #2a2a2a !important;; +.ui-dialog, +.ui-dialog-buttonpane { + background: #2a2a2a !important;; } -.ui-accordion-content, -.ui-tabs-panel { - background: #ededed !important; - background-image: none !important; +.ui-accordion-content, +.ui-tabs-panel { + background: #ededed !important; + background-image: none !important; } -.ui-widget-content { +.ui-widget-content { background: #606060; border: 1px solid #111; color: #fff; @@ -208,82 +204,82 @@ inc_top.tmpl color: #09A2FF; } -.ui-widget-header { +.ui-widget-header { background: #3d3d3d; border: 1px solid #111; color: #fff; } -.ui-state-default, -.ui-widget-content .ui-state-default, -.ui-widget-header .ui-state-default { +.ui-state-default, +.ui-widget-content .ui-state-default, +.ui-widget-header .ui-state-default { border: 1px solid #111; } -.ui-state-hover, -.ui-widget-content .ui-state-hover, -.ui-widget-header .ui-state-hover, -.ui-state-focus, -.ui-widget-content .ui-state-focus, -.ui-widget-header .ui-state-focus { - background: #3d3d3d; -} - -.ui-state-active, -.ui-widget-content .ui-state-active, -.ui-widget-header .ui-state-active { +.ui-state-hover, +.ui-widget-content .ui-state-hover, +.ui-widget-header .ui-state-hover, +.ui-state-focus, +.ui-widget-content .ui-state-focus, +.ui-widget-header .ui-state-focus { background: #3d3d3d; } -.ui-state-highlight, -.ui-widget-content .ui-state-highlight, -.ui-widget-header .ui-state-highlight { - background: #fbf9ee url("../css/lib/images/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x; +.ui-state-active, +.ui-widget-content .ui-state-active, +.ui-widget-header .ui-state-active { + background: #3d3d3d; } -.ui-state-error, -.ui-widget-content .ui-state-error, -.ui-widget-header .ui-state-error { - background: #fef1ec url("../css/lib/images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x; +.ui-state-highlight, +.ui-widget-content .ui-state-highlight, +.ui-widget-header .ui-state-highlight { + background: #fbf9ee url("../css/lib/images/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x; } -.ui-icon, -.ui-widget-content .ui-icon { - background-image: url("../css/lib/images/ui-icons_ffffff_256x240.png"); +.ui-state-error, +.ui-widget-content .ui-state-error, +.ui-widget-header .ui-state-error { + background: #fef1ec url("../css/lib/images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x; } -.ui-widget-header .ui-icon { - background-image: url("../css/lib/images/ui-icons_222222_256x240.png"); +.ui-icon, +.ui-widget-content .ui-icon { + background-image: url("../css/lib/images/ui-icons_ffffff_256x240.png"); } -.ui-state-default .ui-icon { - background-image: url('../css/lib/images/ui-icons_09a2ff_256x240.png'); +.ui-widget-header .ui-icon { + background-image: url("../css/lib/images/ui-icons_222222_256x240.png"); } -.ui-state-hover .ui-icon, -.ui-state-focus .ui-icon { - background-image: url("../css/lib/images/ui-icons_222222_256x240.png"); +.ui-state-default .ui-icon { + background-image: url('../css/lib/images/ui-icons_09a2ff_256x240.png'); } -.ui-state-active .ui-icon { - background-image: url("../css/lib/images/ui-icons_8c291d_256x240.png"); +.ui-state-hover .ui-icon, +.ui-state-focus .ui-icon { + background-image: url("../css/lib/images/ui-icons_222222_256x240.png"); } -.ui-state-highlight .ui-icon { - background-image: url("../css/lib/images/ui-icons_2e83ff_256x240.png"); +.ui-state-active .ui-icon { + background-image: url("../css/lib/images/ui-icons_8c291d_256x240.png"); } -.ui-state-error .ui-icon, -.ui-state-error-text .ui-icon { - background-image: url("../css/lib/images/ui-icons_cd0a0a_256x240.png"); +.ui-state-highlight .ui-icon { + background-image: url("../css/lib/images/ui-icons_2e83ff_256x240.png"); } -.ui-widget-overlay { - background: #000000 url("../css/lib/images/ui-bg_flat_0_000000_40x100.png") 50% 50% repeat-x; +.ui-state-error .ui-icon, +.ui-state-error-text .ui-icon { + background-image: url("../css/lib/images/ui-icons_cd0a0a_256x240.png"); } -.ui-widget-shadow { - background: #000000 url("../css/lib/images/ui-bg_flat_0_000000_40x100.png") 50% 50% repeat-x; +.ui-widget-overlay { + background: #000000 url("../css/lib/images/ui-bg_flat_0_000000_40x100.png") 50% 50% repeat-x; +} + +.ui-widget-shadow { + background: #000000 url("../css/lib/images/ui-bg_flat_0_000000_40x100.png") 50% 50% repeat-x; } .ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { @@ -301,21 +297,21 @@ inc_top.tmpl } .ui-tabs { - padding: 0px; + padding: 0; background: none; - border-width: 0px; + border-width: 0; } .ui-tabs .ui-tabs-nav { - padding-left: 0px; + padding-left: 0; background: transparent; - border-width: 0px 0px 0px 0px; - -moz-border-radius: 0px; - -webkit-border-radius: 0px; - border-radius: 0px; + border-width: 0 0 0 0; + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; } -.ui-tabs .ui-tabs-panel { +.ui-tabs .ui-tabs-panel { background-color: #3d3d3d !important; border: 1px solid #111 !important; } @@ -331,15 +327,6 @@ inc_top.tmpl border-top-right-radius: 5px; } -#content { - width: 95%; - min-width: 875px; - padding: 15px; - margin-left: auto; - margin-right: auto; - clear: both; -} - #SubMenu { padding-right: 20px; clear: both; @@ -348,12 +335,12 @@ inc_top.tmpl } .upgrade-notification { - width: 600px; - text-align: center; - margin-left: auto; - margin-right: auto; - margin-top: 50px; - margin-bottom: 0px; + width: 600px; + text-align: center; + margin-left: auto; + margin-right: auto; + margin-top: 50px; + margin-bottom: 0; } [class^="menu-icon-"], [class*=" menu-icon-"] { @@ -379,83 +366,83 @@ inc_top.tmpl } .menu-icon-addshow { - background-position: 0px 0px; + background-position: 0 0; } .menu-icon-anime { - background-position: -21px 0px; + background-position: -21px 0; } .menu-icon-backlog-view { - background-position: -42px 0px; + background-position: -42px 0; } .menu-icon-backlog { - background-position: -63px 0px; + background-position: -63px 0; } .menu-icon-bittorrent { - background-position: -84px 0px; + background-position: -84px 0; } .menu-icon-config-index { - background-position: -105px 0px; + background-position: -105px 0; } .menu-icon-config { - background-position: -126px 0px; + background-position: -126px 0; } .menu-icon-failed-download { - background-position: -147px 0px; + background-position: -147px 0; } .menu-icon-home { - background-position: -168px 0px; + background-position: -168px 0; } .menu-icon-manage { - background-position: -189px 0px; + background-position: -189px 0; } .menu-icon-manage-searches { - background-position: -210px 0px; + background-position: -210px 0; } .menu-icon-poster { - background-position: -231px 0px; + background-position: -231px 0; } .menu-icon-postprocess { - background-position: -252px 0px; + background-position: -252px 0; } .menu-icon-restart { - background-position: -273px 0px; + background-position: -273px 0; } .menu-icon-shutdown { - background-position: -294px 0px; + background-position: -294px 0; } .menu-icon-update { - background-position: -315px 0px; + background-position: -315px 0; } .menu-icon-viewlog-errors { - background-position: -336px 0px; + background-position: -336px 0; } .menu-icon-viewlog { - background-position: -357px 0px; + background-position: -357px 0; } .menu-icon-xbmc { - background-position: -378px 0px; + background-position: -378px 0; } .menu-icon-help { - background-position: -399px 0px; + background-position: -399px 0; } [class^="submenu-icon-"], [class*=" submenu-icon-"] { @@ -465,27 +452,27 @@ inc_top.tmpl } .submenu-icon-anime { - background-position: -21px 0px; + background-position: -21px 0; } .submenu-icon-bittorrent { - background-position: -84px 0px; + background-position: -84px 0; } .submenu-icon-failed-download { - background-position: -147px 0px; + background-position: -147px 0; } .submenu-icon-restart { - background-position: -273px 0px; + background-position: -273px 0; } .submenu-icon-shutdown { - background-position: -294px 0px; + background-position: -294px 0; } .submenu-icon-xbmc { - background-position: -378px 0px; + background-position: -378px 0; } /* ======================================================================= @@ -622,42 +609,42 @@ home.tmpl } .show .ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { - border-bottom-right-radius: 0px; + border-bottom-right-radius: 0; } .show .ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { - border-bottom-left-radius: 0px; + border-bottom-left-radius: 0; } .show .ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { - border-top-right-radius: 0px; + border-top-right-radius: 0; } .show .ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { - border-top-left-radius: 0px; + border-top-left-radius: 0; } .show .ui-widget-content { border-top: 1px solid #111; border-bottom: 1px solid #111; - border-left: 0px; - border-right: 0px; + border-left: 0; + border-right: 0; } .show .progress-80 { - border-radius: 0px; + border-radius: 0; } .show .progress-60 { - border-radius: 0px; + border-radius: 0; } .show .progress-40 { - border-radius: 0px; + border-radius: 0; } .show .progress-20 { - border-radius: 0px; + border-radius: 0; } .show-title { @@ -665,7 +652,7 @@ home.tmpl overflow: hidden; white-space: nowrap; font-size: 11px; - margin: 4px 4px 0px 4px; + margin: 4px 4px 0 4px; } .show-title:after { @@ -674,7 +661,7 @@ home.tmpl position: absolute; width: 20px; height: 100%; - top: 0; + top: 0; right: 0; background-image: -webkit-linear-gradient(right, rgba(51, 51, 51, 1), rgba(51, 51, 51, 0)); background-image: -moz-linear-gradient(right, rgba(51, 51, 51, 1), rgba(51, 51, 51, 0)); @@ -688,7 +675,7 @@ home.tmpl overflow: hidden; white-space: nowrap; font-size: 11px; - margin: 0px 4px 4px 4px; + margin: 0 4px 4px 4px; } .show-date:after { @@ -697,7 +684,7 @@ home.tmpl position: absolute; width: 20px; height: 100%; - top: 0; + top: 0; right: 0; background-image: -webkit-linear-gradient(right, rgba(51, 51, 51, 1), rgba(51, 51, 51, 0)); background-image: -moz-linear-gradient(right, rgba(51, 51, 51, 1), rgba(51, 51, 51, 0)); @@ -706,8 +693,8 @@ home.tmpl background-image: linear-gradient(to left, rgba(51, 51, 51, 1), rgba(51, 51, 51, 0)); } -.show-table { - text-align:center; +.show-table { + text-align:center; vertical-align:middle; width: 33% } @@ -745,7 +732,7 @@ home.tmpl #sort-by { display: inline; - list-style-type: none; + list-style-type: none; padding: 0; margin-left: 5px; } @@ -815,20 +802,20 @@ home_trendingShows.tmpl padding-bottom: 4px; } -.traktContainer p { +.traktContainer p { padding-top: 2px; } -.traktContainer p img { +.traktContainer p img { position: relative; top: -2px; } -.traktContainer p, .traktContainer i { +.traktContainer p, .traktContainer i { white-space: nowrap; font-size: 12px; overflow: hidden; -/* text-shadow: 1px 1px 0px #000;*/ +/* text-shadow: 1px 1px 0 #000;*/ padding-left: 4px; margin: 0; } @@ -864,7 +851,7 @@ home_postprocess.tmpl /* ======================================================================= -displayShow.tmpl +displayShow.tmpl ========================================================================== */ #showCol { @@ -894,7 +881,7 @@ h1.title { } .displayspecials { - position: relative; + position: relative; top: -24px; } @@ -902,7 +889,7 @@ h1.title { cursor: default; } -#showinfo { +#showinfo { display: inline-block; position: relative; top: -3px; @@ -928,7 +915,7 @@ ul.tags li { border: 1px solid #111; color: #FFF; font: 14px/18px "Open Sans", "Helvetica Neue", Helvetica, Arial, Geneva, sans-serif; - text-shadow: 0px 1px rgba(0, 0, 0, 0.8); + text-shadow: 0 1px rgba(0, 0, 0, 0.8); float: left; } @@ -1066,7 +1053,7 @@ span.snatched b { white-space: nowrap; } -.sickbeardTable th, +.sickbeardTable th, .sickbeardTable td { border-top: 1px solid #222; border-left: 1px solid #222; @@ -1168,7 +1155,7 @@ td.col-search { } /* ======================================================================= -comingEpisodes.tmpl +episodeView.tmpl ========================================================================== */ .sort_data { @@ -1227,7 +1214,7 @@ h2.day, h2.network { letter-spacing: 1px; color: #FFF; text-align: center; - text-shadow: -1px -1px 0px rgba(0, 0, 0, 0.3); + text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.3); background-color: #15528F; } @@ -1236,7 +1223,7 @@ h2.day, h2.network { clear: both; border: 1px solid #ccc; margin: auto; - padding: 0px; + padding: 0; text-align: left; width: 750px; border-radius: 5px; @@ -1325,7 +1312,7 @@ h2.day, h2.network { color: #09A2FF; } -.calendar-row .day-number { +.day-of-week .day-number { background-color: #15528F; color: #fff; } @@ -1334,22 +1321,34 @@ h2.day, h2.network { color: #8dbeee; } -.odd .calendar-show { +.odd .daybyday-show { background-color: #333; } -.even .calendar-show { +.even .daybyday-show { background-color: #3d3d3d; } - -.calendar-row .poster img { - border: 1px solid #111; +.daybyday-show .episode-blank { + background-color: rgba(0,0,0,.1); + border-radius: 3px; } -.calendar-row .text .airtime, -.calendar-row .text .episode-title { +.day-of-week .poster img { + border-color: #111; +} + +.day-of-week .text .airtime, +.day-of-week .text .episode, +.day-of-week .text .episode .name { color: #fff; } +.day-of-week .text .episode .season, +.day-of-week .text .episode .number { + color: rgb(9, 162, 255); +} +.day-of-week .text .episode { + color: rgb(141, 190, 238); +} /* ======================================================================= config*.tmpl @@ -1385,7 +1384,7 @@ config*.tmpl } #config div.field-pair { - padding: 12px 0px; + padding: 12px 0; } #config .nocheck, #config div #customQuality, .metadataDiv { @@ -1423,14 +1422,14 @@ select .selected { list-style-type: none; } -#provider_order_list, +#provider_order_list, #service_order_list { width: 250px; padding-left: 20px; list-style-type: none; } -#provider_order_list li, +#provider_order_list li, #service_order_list li { background: #333 !important; color: #fff; @@ -1447,13 +1446,13 @@ select .selected { width: 220px !important; } -.infoTableHeader, +.infoTableHeader, .infoTableCell { padding: 5px; } -.infoTableSeperator { - border-top: 1px dotted #666666; +.infoTableSeperator { + border-top: 1px dotted #666666; } /* ======================================================================= @@ -1570,7 +1569,7 @@ td.tableright { text-align: left; vertical-align: middle; width: 225px; - padding: 6px 0px; + padding: 6px 0; } .optionWrapper div.selectChoices { @@ -1604,7 +1603,6 @@ Global ========================================================================== */ span.path { - padding: 3px 6px; color: #09A2FF; background-color: #333; } @@ -1616,13 +1614,13 @@ span.path { span.quality { font: 12px/13px "Open Sans", verdana, sans-serif; - background-image:-webkit-linear-gradient(top, rgba(255,255,255,0.08),rgba(255,255,255,0) 50%,rgba(0,0,0,0) 50%,rgba(0,0,0,0.25)); - background-image:-moz-linear-gradient(top, rgba(255,255,255,0.08),rgba(255,255,255,0) 50%,rgba(0,0,0,0) 50%,rgba(0,0,0,0.25)); - background-image:-o-linear-gradient(top, rgba(255,255,255,0.08),rgba(255,255,255,0) 50%,rgba(0,0,0,0) 50%,rgba(0,0,0,0.25)); - background-image:linear-gradient(to bottom, rgba(255,255,255,0.08),rgba(255,255,255,0) 50%,rgba(0,0,0,0) 50%,rgba(0,0,0,0.25)); - -webkit-box-shadow:inset 0 1px rgba(255,255,255,0.1),inset 0 -1px 3px rgba(0,0,0,0.3),inset 0 0 0 1px rgba(255,255,255,0.08),0 1px 2px rgba(0,0,0,0.15); - box-shadow:inset 0 1px rgba(255,255,255,0.1),inset 0 -1px 3px rgba(0,0,0,0.3),inset 0 0 0 1px rgba(255,255,255,0.08),0 1px 2px rgba(0,0,0,0.15); - text-shadow: 0px 1px rgba(0, 0, 0, 0.8); + background-image:-webkit-linear-gradient(top, rgba(255, 255, 255, 0.08),rgba(255, 255, 255, 0) 50%,rgba(0, 0, 0, 0) 50%,rgba(0, 0, 0, 0.25)); + background-image:-moz-linear-gradient(top, rgba(255, 255, 255, 0.08),rgba(255, 255, 255, 0) 50%,rgba(0, 0, 0, 0) 50%,rgba(0, 0, 0, 0.25)); + background-image:-o-linear-gradient(top, rgba(255, 255, 255, 0.08),rgba(255, 255, 255, 0) 50%,rgba(0, 0, 0, 0) 50%,rgba(0, 0, 0, 0.25)); + background-image:linear-gradient(to bottom, rgba(255, 255, 255, 0.08),rgba(255, 255, 255, 0) 50%,rgba(0, 0, 0, 0) 50%,rgba(0, 0, 0, 0.25)); + -webkit-box-shadow:inset 0 1px rgba(255, 255, 255, 0.1),inset 0 -1px 3px rgba(0, 0, 0, 0.3),inset 0 0 0 1px rgba(255, 255, 255, 0.08),0 1px 2px rgba(0, 0, 0, 0.15); + box-shadow:inset 0 1px rgba(255, 255, 255, 0.1),inset 0 -1px 3px rgba(0, 0, 0, 0.3),inset 0 0 0 1px rgba(255, 255, 255, 0.08),0 1px 2px rgba(0, 0, 0, 0.15); + text-shadow: 0 1px rgba(0, 0, 0, 0.8); color: #FFFFFF; display: inline-block; padding: 2px 4px; @@ -1713,7 +1711,7 @@ option.flag { div.blackwhitelist{ float:left; - text-align: center; + text-align: center; } div.blackwhitelist input { @@ -1742,7 +1740,7 @@ div.blackwhitelist span { } div.blackwhitelist.anidb, div.blackwhitelist.manual { - margin: 7px 0px; + margin: 7px 0; } @@ -1750,8 +1748,8 @@ div.blackwhitelist.anidb, div.blackwhitelist.manual { bootstrap Overrides ========================================================================== */ -body { - padding-top: 60px; +body { + padding-top: 60px; overflow-y: scroll; font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; color: #fff; @@ -1759,7 +1757,7 @@ body { } input[type="radio"] { - margin: 2px 0px 0px; + margin: 2px 0 0; line-height: normal; } @@ -1774,7 +1772,7 @@ input, textarea, select, .uneditable-input { } .navbar-brand { - padding: 0px; + padding: 0; } /* navbar styling */ @@ -1914,7 +1912,7 @@ fieldset[disabled] .navbar-default .btn-link:focus { .dropdown-menu { background-color: #333; border: 1px solid rgba(0, 0, 0, 0.15); - box-shadow: 0px 6px 12px rgba(0, 0, 0, 0.176); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.176); } .form-control { @@ -2392,10 +2390,10 @@ pnotify.css background-image: -o-linear-gradient(#333, #3d3d3d) !important; filter: progid:dximagetransform.microsoft.gradient(startColorstr=#333, endColorstr=#3d3d3d) !important; -ms-filter: progid:dximagetransform.microsoft.gradient(startColorstr=#333, endColorstr=#3d3d3d) !important; - -moz-box-shadow: 0px 0px 2px #000; - -webkit-box-shadow: 0px 0px 2px #000; - -o-box-shadow: 0px 0px 2px #000; - box-shadow: 0px 0px 2px #000; + -moz-box-shadow: 0 0 2px #000; + -webkit-box-shadow: 0 0 2px #000; + -o-box-shadow: 0 0 2px #000; + box-shadow: 0 0 2px #000; } .ui-pnotify-title { @@ -2433,7 +2431,7 @@ tablesorter.css .tablesorter th { color: #fff; - text-shadow: -1px -1px 0 rgba(0,0,0,0.3); + text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.3); background-color: #15528F; } @@ -2504,7 +2502,7 @@ thead.tablesorter-stickyHeader { .tablesorter tfoot tr { color: #fff; text-align: center; - text-shadow: -1px -1px 0 rgba(0,0,0,0.3); + text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.3); background-color: #333; border-collapse: collapse; } @@ -2656,10 +2654,19 @@ span.token-input-delete-token { background-color: rgb(40, 40, 40); } +/*.episodeview-daybyday .time .time-min,*/ +.episodeview-daybyday .time .time-hr-min, +.episodeview-daybyday .time .time-am-pm, #addRootDirTable td label .filepath, .grey-text { color:#999 } +/*.episodeview-daybyday .time .time-hr-min{ + display:none +} +.episodeview-daybyday .time .time-min{ + font-size: 11px; +}*/ #newShowPortal #displayText .show-name, #newShowPortal #displayText .show-dest, @@ -2682,8 +2689,8 @@ jquery.confirm.css top: 0; left: 0; 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); + 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; } @@ -2695,7 +2702,7 @@ jquery.confirm.css top: 50%; margin: -130px 0 0 -230px; border: 1px solid #111; - box-shadow: 0px 0px 12px 0px rgba(0, 0, 0, 0.175); + box-shadow: 0 0 12px 0 rgba(0, 0, 0, 0.175); } #confirmBox h1, @@ -2709,13 +2716,13 @@ jquery.confirm.css color: #fff; margin: 0; font-size: 22px; - text-shadow: 0px 1px 1px rgba(0, 0, 0, 0.75); + text-shadow: 0 1px 1px rgba(0, 0, 0, 0.75); } #confirmBox p { padding-top: 20px; color: #fff; - text-shadow: 0px 1px 1px rgba(0, 0, 0, 0.75); + text-shadow: 0 1px 1px rgba(0, 0, 0, 0.75); } #confirmButtons { @@ -2730,7 +2737,7 @@ jquery.confirm.css display: inline-block; color: #fff; text-align:center; - text-shadow: 0px 1px 1px rgba(0, 0, 0, 0.75); + text-shadow: 0 1px 1px rgba(0, 0, 0, 0.75); background-clip: padding-box; border: 1px solid #111; border-radius: 3px; @@ -2738,12 +2745,12 @@ jquery.confirm.css -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; - background-image: -webkit-linear-gradient(top, rgba(255,255,255,0.08),rgba(255,255,255,0) 50%,rgba(0,0,0,0) 51%,rgba(0,0,0,0.25)); - background-image: -moz-linear-gradient(top, rgba(255,255,255,0.08),rgba(255,255,255,0) 50%,rgba(0,0,0,0) 51%,rgba(0,0,0,0.25)); - background-image: -o-linear-gradient(top, rgba(255,255,255,0.08),rgba(255,255,255,0) 50%,rgba(0,0,0,0) 51%,rgba(0,0,0,0.25)); - background-image: linear-gradient(to bottom, rgba(255,255,255,0.08),rgba(255,255,255,0) 50%,rgba(0,0,0,0) 51%,rgba(0,0,0,0.25)); - -webkit-box-shadow: inset 0 1px rgba(255,255,255,0.1),inset 0 -1px 3px rgba(0,0,0,0.3),inset 0 0 0 1px rgba(255,255,255,0.08),0 1px 2px rgba(0,0,0,0.15); - box-shadow: inset 0 1px rgba(255,255,255,0.1),inset 0 -1px 3px rgba(0,0,0,0.3),inset 0 0 0 1px rgba(255,255,255,0.08),0 1px 2px rgba(0,0,0,0.15); + background-image: -webkit-linear-gradient(top, rgba(255, 255, 255, 0.08),rgba(255, 255, 255, 0) 50%,rgba(0, 0, 0, 0) 51%,rgba(0, 0, 0, 0.25)); + background-image: -moz-linear-gradient(top, rgba(255, 255, 255, 0.08),rgba(255, 255, 255, 0) 50%,rgba(0, 0, 0, 0) 51%,rgba(0, 0, 0, 0.25)); + background-image: -o-linear-gradient(top, rgba(255, 255, 255, 0.08),rgba(255, 255, 255, 0) 50%,rgba(0, 0, 0, 0) 51%,rgba(0, 0, 0, 0.25)); + background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0.08),rgba(255, 255, 255, 0) 50%,rgba(0, 0, 0, 0) 51%,rgba(0, 0, 0, 0.25)); + -webkit-box-shadow: inset 0 1px rgba(255, 255, 255, 0.1),inset 0 -1px 3px rgba(0, 0, 0, 0.3),inset 0 0 0 1px rgba(255, 255, 255, 0.08),0 1px 2px rgba(0, 0, 0, 0.15); + box-shadow: inset 0 1px rgba(255, 255, 255, 0.1),inset 0 -1px 3px rgba(0, 0, 0, 0.3),inset 0 0 0 1px rgba(255, 255, 255, 0.08),0 1px 2px rgba(0, 0, 0, 0.15); } #confirmBox .button:last-child { diff --git a/gui/slick/css/light.css b/gui/slick/css/light.css index fc2dd64d..8ebbbfe5 100644 --- a/gui/slick/css/light.css +++ b/gui/slick/css/light.css @@ -149,11 +149,7 @@ inc_top.tmpl margin-bottom: -15px; } -#contentWrapper { -/* background: url("../images/bg.png") repeat 0 0 transparent; */ -} - -[class^="icon-"], +[class^="icon-"], [class*=" icon-"] { background-image: url("../images/glyphicons-halflings.png"); } @@ -289,18 +285,18 @@ inc_top.tmpl } .ui-tabs { - padding: 0px; + padding: 0; background: none; - border-width: 0px; + border-width: 0; } .ui-tabs .ui-tabs-nav { - padding-left: 0px; + padding-left: 0; background: transparent; - border-width: 0px 0px 0px 0px; - -moz-border-radius: 0px; - -webkit-border-radius: 0px; - border-radius: 0px; + border-width: 0 0 0 0; + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; } .ui-tabs .ui-tabs-panel { @@ -318,15 +314,6 @@ inc_top.tmpl border-top-right-radius: 5px; } -#content { - width: 95%; - min-width: 875px; - padding: 15px; - margin-left: auto; - margin-right: auto; - clear: both; -} - #SubMenu { padding-right: 20px; clear: both; @@ -340,7 +327,7 @@ inc_top.tmpl margin-left: auto; margin-right: auto; margin-top: 50px; - margin-bottom: 0px; + margin-bottom: 0; } [class^="menu-icon-"], [class*=" menu-icon-"] { @@ -366,83 +353,83 @@ inc_top.tmpl } .menu-icon-addshow { - background-position: 0px 0px; + background-position: 0 0; } .menu-icon-anime { - background-position: -21px 0px; + background-position: -21px 0; } .menu-icon-backlog-view { - background-position: -42px 0px; + background-position: -42px 0; } .menu-icon-backlog { - background-position: -63px 0px; + background-position: -63px 0; } .menu-icon-bittorrent { - background-position: -84px 0px; + background-position: -84px 0; } .menu-icon-config-index { - background-position: -105px 0px; + background-position: -105px 0; } .menu-icon-config { - background-position: -126px 0px; + background-position: -126px 0; } .menu-icon-failed-download { - background-position: -147px 0px; + background-position: -147px 0; } .menu-icon-home { - background-position: -168px 0px; + background-position: -168px 0; } .menu-icon-manage { - background-position: -189px 0px; + background-position: -189px 0; } .menu-icon-manage-searches { - background-position: -210px 0px; + background-position: -210px 0; } .menu-icon-poster { - background-position: -231px 0px; + background-position: -231px 0; } .menu-icon-postprocess { - background-position: -252px 0px; + background-position: -252px 0; } .menu-icon-restart { - background-position: -273px 0px; + background-position: -273px 0; } .menu-icon-shutdown { - background-position: -294px 0px; + background-position: -294px 0; } .menu-icon-update { - background-position: -315px 0px; + background-position: -315px 0; } .menu-icon-viewlog-errors { - background-position: -336px 0px; + background-position: -336px 0; } .menu-icon-viewlog { - background-position: -357px 0px; + background-position: -357px 0; } .menu-icon-xbmc { - background-position: -378px 0px; + background-position: -378px 0; } .menu-icon-help { - background-position: -399px 0px; + background-position: -399px 0; } [class^="submenu-icon-"], [class*=" submenu-icon-"] { @@ -452,27 +439,27 @@ inc_top.tmpl } .submenu-icon-anime { - background-position: -21px 0px; + background-position: -21px 0; } .submenu-icon-bittorrent { - background-position: -84px 0px; + background-position: -84px 0; } .submenu-icon-failed-download { - background-position: -147px 0px; + background-position: -147px 0; } .submenu-icon-restart { - background-position: -273px 0px; + background-position: -273px 0; } .submenu-icon-shutdown { - background-position: -294px 0px; + background-position: -294px 0; } .submenu-icon-xbmc { - background-position: -378px 0px; + background-position: -378px 0; } /* ======================================================================= @@ -609,42 +596,42 @@ home.tmpl } .show .ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { - border-bottom-right-radius: 0px; + border-bottom-right-radius: 0; } .show .ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { - border-bottom-left-radius: 0px; + border-bottom-left-radius: 0; } .show .ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { - border-top-right-radius: 0px; + border-top-right-radius: 0; } .show .ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { - border-top-left-radius: 0px; + border-top-left-radius: 0; } .show .ui-widget-content { border-top: 1px solid #111; border-bottom: 1px solid #111; - border-left: 0px; - border-right: 0px; + border-left: 0; + border-right: 0; } .show .progress-80 { - border-radius: 0px; + border-radius: 0; } .show .progress-60 { - border-radius: 0px; + border-radius: 0; } .show .progress-40 { - border-radius: 0px; + border-radius: 0; } .show .progress-20 { - border-radius: 0px; + border-radius: 0; } .show-title { @@ -652,7 +639,7 @@ home.tmpl overflow: hidden; white-space: nowrap; font-size: 11px; - margin: 4px 4px 0px 4px; + margin: 4px 4px 0 4px; } .show-title:after { @@ -675,7 +662,7 @@ home.tmpl overflow: hidden; white-space: nowrap; font-size: 11px; - margin: 0px 4px 4px 4px; + margin: 0 4px 4px 4px; } .show-date:after { @@ -815,7 +802,7 @@ home_trendingShows.tmpl white-space: nowrap; font-size: 12px; overflow: hidden; -/* text-shadow: 1px 1px 0px #000;*/ +/* text-shadow: 1px 1px 0 #000;*/ padding-left: 4px; margin: 0; } @@ -917,7 +904,7 @@ ul.tags li { border: 1px solid #111; color: #FFF; font: 14px/18px "Open Sans", "Helvetica Neue", Helvetica, Arial, Geneva, sans-serif; - text-shadow: 0px 1px rgba(0, 0, 0, 0.8); + text-shadow: 0 1px rgba(0, 0, 0, 0.8); float: left; } @@ -1074,7 +1061,7 @@ tr.seasonheader { padding-top: 10px; text-align: left; border: none; - color: #fff; + color: #000; } th.col-checkbox, @@ -1157,7 +1144,7 @@ td.col-search { } /* ======================================================================= -comingEpisodes.tmpl +episodeView.tmpl ========================================================================== */ .sort_data { @@ -1219,7 +1206,7 @@ h2.day, h2.network { letter-spacing: 1px; color: #FFF; text-align: center; - text-shadow: -1px -1px 0px rgba(0, 0, 0, 0.3); + text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.3); background-color: #333; } @@ -1228,7 +1215,7 @@ h2.day, h2.network { clear: both; border: 1px solid #ccc; margin: auto; - padding: 0px; + padding: 0; text-align: left; width: 750px; border-radius: 5px; @@ -1307,7 +1294,7 @@ h2.day, h2.network { vertical-align: middle; } -.calendar-row .day-number { +.day-of-week .day-number { background-color: #333; color: #fff; } @@ -1316,22 +1303,31 @@ h2.day, h2.network { color: #c7db40; } -.odd .calendar-show { +.odd .daybyday-show { background-color: #F5F1E4; } -.even .calendar-show { +.even .daybyday-show { background-color: #DFDACF; } -.calendar-row .poster img { - border: 1px solid #CCC; +.day-of-week .poster img { + border-color: #CCC; } -.calendar-row .text .airtime, -.calendar-row .text .episode-title { +.day-of-week .text .airtime, +.day-of-week .text .episode, +.day-of-week .text .episode .name { color: #000; } +.day-of-week .text .episode .season, +.day-of-week .text .episode .number { + color: rgb(9, 133, 225); + /*color: #3d3d3d;*/ +} +.day-of-week .text .episode { + color: #888; +} /* ======================================================================= config*.tmpl @@ -1368,7 +1364,7 @@ config*.tmpl } #config div.field-pair { - padding: 12px 0px; + padding: 12px 0; } #config .nocheck, #config div #customQuality, .metadataDiv { @@ -1546,7 +1542,7 @@ td.tableright { text-align: left; vertical-align: middle; width: 225px; - padding: 6px 0px; + padding: 6px 0; } .optionWrapper div.selectChoices { @@ -1580,7 +1576,6 @@ Global ========================================================================== */ span.path { - padding: 3px 6px; color: #8b0000; background-color: #f5f1e4; } @@ -1596,13 +1591,13 @@ span.path { span.quality { font: 12px/13px "Open Sans", verdana, sans-serif; - background-image:-webkit-linear-gradient(top, rgba(255,255,255,0.08),rgba(255,255,255,0) 50%,rgba(0,0,0,0) 50%,rgba(0,0,0,0.25)); - background-image:-moz-linear-gradient(top, rgba(255,255,255,0.08),rgba(255,255,255,0) 50%,rgba(0,0,0,0) 50%,rgba(0,0,0,0.25)); - background-image:-o-linear-gradient(top, rgba(255,255,255,0.08),rgba(255,255,255,0) 50%,rgba(0,0,0,0) 50%,rgba(0,0,0,0.25)); - background-image:linear-gradient(to bottom, rgba(255,255,255,0.08),rgba(255,255,255,0) 50%,rgba(0,0,0,0) 50%,rgba(0,0,0,0.25)); - -webkit-box-shadow:inset 0 1px rgba(255,255,255,0.1),inset 0 -1px 3px rgba(0,0,0,0.3),inset 0 0 0 1px rgba(255,255,255,0.08),0 1px 2px rgba(0,0,0,0.15); - box-shadow:inset 0 1px rgba(255,255,255,0.1),inset 0 -1px 3px rgba(0,0,0,0.3),inset 0 0 0 1px rgba(255,255,255,0.08),0 1px 2px rgba(0,0,0,0.15); - text-shadow: 0px 1px rgba(0, 0, 0, 0.8); + background-image:-webkit-linear-gradient(top, rgba(255, 255, 255, 0.08),rgba(255, 255, 255, 0) 50%,rgba(0, 0, 0, 0) 50%,rgba(0, 0, 0, 0.25)); + background-image:-moz-linear-gradient(top, rgba(255, 255, 255, 0.08),rgba(255, 255, 255, 0) 50%,rgba(0, 0, 0, 0) 50%,rgba(0, 0, 0, 0.25)); + background-image:-o-linear-gradient(top, rgba(255, 255, 255, 0.08),rgba(255, 255, 255, 0) 50%,rgba(0, 0, 0, 0) 50%,rgba(0, 0, 0, 0.25)); + background-image:linear-gradient(to bottom, rgba(255, 255, 255, 0.08),rgba(255, 255, 255, 0) 50%,rgba(0, 0, 0, 0) 50%,rgba(0, 0, 0, 0.25)); + -webkit-box-shadow:inset 0 1px rgba(255, 255, 255, 0.1),inset 0 -1px 3px rgba(0, 0, 0, 0.3),inset 0 0 0 1px rgba(255, 255, 255, 0.08),0 1px 2px rgba(0, 0, 0, 0.15); + box-shadow:inset 0 1px rgba(255, 255, 255, 0.1),inset 0 -1px 3px rgba(0, 0, 0, 0.3),inset 0 0 0 1px rgba(255, 255, 255, 0.08),0 1px 2px rgba(0, 0, 0, 0.15); + text-shadow: 0 1px rgba(0, 0, 0, 0.8); color: #FFFFFF; display: inline-block; padding: 2px 4px; @@ -1693,7 +1688,7 @@ option.flag { div.blackwhitelist{ float:left; - text-align: center; + text-align: center; } div.blackwhitelist input { @@ -1722,7 +1717,7 @@ div.blackwhitelist span { } div.blackwhitelist.anidb, div.blackwhitelist.manual { - margin: 7px 0px; + margin: 7px 0; } @@ -1730,15 +1725,15 @@ div.blackwhitelist.anidb, div.blackwhitelist.manual { bootstrap Overrides ========================================================================== */ -body { - padding-top: 60px; +body { + padding-top: 60px; overflow-y: scroll; font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; color: #000; } input[type="radio"] { - margin: 2px 0px 0px; + margin: 2px 0 0; line-height: normal; } @@ -1753,7 +1748,7 @@ input, textarea, select, .uneditable-input { } .navbar-brand { - padding: 0px; + padding: 0; } /* navbar styling */ @@ -1892,7 +1887,7 @@ fieldset[disabled] .navbar-default .btn-link:focus { .dropdown-menu { background-color: #F5F1E4; border: 1px solid rgba(0, 0, 0, 0.15); - box-shadow: 0px 6px 12px rgba(0, 0, 0, 0.176); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.176); } .form-control { @@ -2386,7 +2381,7 @@ tablesorter.css .tablesorter th { color: #fff; - text-shadow: -1px -1px 0 rgba(0,0,0,0.3); + text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.3); background-color: #333; } @@ -2457,7 +2452,7 @@ thead.tablesorter-stickyHeader { .tablesorter tfoot tr { color: #fff; text-align: center; - text-shadow: -1px -1px 0 rgba(0,0,0,0.3); + text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.3); background-color: #333; border-collapse: collapse; } @@ -2604,6 +2599,8 @@ span.token-input-delete-token { background-color: rgb(245, 245, 245); } +.episodeview-daybyday .time .time-min, +.episodeview-daybyday .time .time-am-pm, #addRootDirTable td label .filepath, .grey-text { color:#666 @@ -2630,8 +2627,8 @@ jquery.confirm.css top: 0; left: 0; 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); + 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; } @@ -2643,7 +2640,7 @@ jquery.confirm.css top: 50%; margin: -130px 0 0 -230px; border: 1px solid #111; - box-shadow: 0px 0px 12px 0px rgba(0, 0, 0, 0.175); + box-shadow: 0 0 12px 0 rgba(0, 0, 0, 0.175); } #confirmBox h1, @@ -2657,13 +2654,13 @@ jquery.confirm.css color: #fff; margin: 0; font-size: 22px; - text-shadow: 0px 1px 1px rgba(0, 0, 0, 0.75); + text-shadow: 0 1px 1px rgba(0, 0, 0, 0.75); } #confirmBox p { padding-top: 20px; color: #000; - text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.75); + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); } #confirmButtons { @@ -2678,7 +2675,7 @@ jquery.confirm.css display: inline-block; color: #fff; text-align:center; - text-shadow: 0px 1px 1px rgba(0, 0, 0, 0.75); + text-shadow: 0 1px 1px rgba(0, 0, 0, 0.75); background-clip: padding-box; border: 1px solid #111; border-radius: 3px; @@ -2686,12 +2683,12 @@ jquery.confirm.css -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; - background-image: -webkit-linear-gradient(top, rgba(255,255,255,0.08),rgba(255,255,255,0) 50%,rgba(0,0,0,0) 51%,rgba(0,0,0,0.25)); - background-image: -moz-linear-gradient(top, rgba(255,255,255,0.08),rgba(255,255,255,0) 50%,rgba(0,0,0,0) 51%,rgba(0,0,0,0.25)); - background-image: -o-linear-gradient(top, rgba(255,255,255,0.08),rgba(255,255,255,0) 50%,rgba(0,0,0,0) 51%,rgba(0,0,0,0.25)); - background-image: linear-gradient(to bottom, rgba(255,255,255,0.08),rgba(255,255,255,0) 50%,rgba(0,0,0,0) 51%,rgba(0,0,0,0.25)); - -webkit-box-shadow: inset 0 1px rgba(255,255,255,0.1),inset 0 -1px 3px rgba(0,0,0,0.3),inset 0 0 0 1px rgba(255,255,255,0.08),0 1px 2px rgba(0,0,0,0.15); - box-shadow: inset 0 1px rgba(255,255,255,0.1),inset 0 -1px 3px rgba(0,0,0,0.3),inset 0 0 0 1px rgba(255,255,255,0.08),0 1px 2px rgba(0,0,0,0.15); + background-image: -webkit-linear-gradient(top, rgba(255, 255, 255, 0.08),rgba(255, 255, 255, 0) 50%,rgba(0, 0, 0, 0) 51%,rgba(0, 0, 0, 0.25)); + background-image: -moz-linear-gradient(top, rgba(255, 255, 255, 0.08),rgba(255, 255, 255, 0) 50%,rgba(0, 0, 0, 0) 51%,rgba(0, 0, 0, 0.25)); + background-image: -o-linear-gradient(top, rgba(255, 255, 255, 0.08),rgba(255, 255, 255, 0) 50%,rgba(0, 0, 0, 0) 51%,rgba(0, 0, 0, 0.25)); + background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0.08),rgba(255, 255, 255, 0) 50%,rgba(0, 0, 0, 0) 51%,rgba(0, 0, 0, 0.25)); + -webkit-box-shadow: inset 0 1px rgba(255, 255, 255, 0.1),inset 0 -1px 3px rgba(0, 0, 0, 0.3),inset 0 0 0 1px rgba(255, 255, 255, 0.08),0 1px 2px rgba(0, 0, 0, 0.15); + box-shadow: inset 0 1px rgba(255, 255, 255, 0.1),inset 0 -1px 3px rgba(0, 0, 0, 0.3),inset 0 0 0 1px rgba(255, 255, 255, 0.08),0 1px 2px rgba(0, 0, 0, 0.15); } #confirmBox .button:last-child { diff --git a/gui/slick/css/style.css b/gui/slick/css/style.css index 53dbb1c9..d9d2351a 100644 --- a/gui/slick/css/style.css +++ b/gui/slick/css/style.css @@ -149,8 +149,11 @@ inc_top.tmpl margin-bottom: -15px; } -#contentWrapper { -/* background: url("../images/bg.png") repeat 0 0 transparent; */ +#contentWrapper .episodeview-banner, +#contentWrapper .episodeview-daybyday, +#contentWrapper .episodeview-list, +#contentWrapper .episodeview-poster{ + padding-top:45px; } [class^="icon-"], @@ -285,18 +288,18 @@ inc_top.tmpl } .ui-tabs { - padding: 0px; + padding: 0; background: none; - border-width: 0px; + border-width: 0; } .ui-tabs .ui-tabs-nav { - padding-left: 0px; + padding-left: 0; background: transparent; - border-width: 0px 0px 0px 0px; - -moz-border-radius: 0px; - -webkit-border-radius: 0px; - border-radius: 0px; + border-width: 0 0 0 0; + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; } .ui-tabs .ui-tabs-panel { @@ -336,7 +339,7 @@ inc_top.tmpl margin-left: auto; margin-right: auto; margin-top: 50px; - margin-bottom: 0px; + margin-bottom: 0; } [class^="menu-icon-"], [class*=" menu-icon-"] { @@ -362,83 +365,83 @@ inc_top.tmpl } .menu-icon-addshow { - background-position: 0px 0px; + background-position: 0 0; } .menu-icon-anime { - background-position: -21px 0px; + background-position: -21px 0; } .menu-icon-backlog-view { - background-position: -42px 0px; + background-position: -42px 0; } .menu-icon-backlog { - background-position: -63px 0px; + background-position: -63px 0; } .menu-icon-bittorrent { - background-position: -84px 0px; + background-position: -84px 0; } .menu-icon-config-index { - background-position: -105px 0px; + background-position: -105px 0; } .menu-icon-config { - background-position: -126px 0px; + background-position: -126px 0; } .menu-icon-failed-download { - background-position: -147px 0px; + background-position: -147px 0; } .menu-icon-home { - background-position: -168px 0px; + background-position: -168px 0; } .menu-icon-manage { - background-position: -189px 0px; + background-position: -189px 0; } .menu-icon-manage-searches { - background-position: -210px 0px; + background-position: -210px 0; } .menu-icon-poster { - background-position: -231px 0px; + background-position: -231px 0; } .menu-icon-postprocess { - background-position: -252px 0px; + background-position: -252px 0; } .menu-icon-restart { - background-position: -273px 0px; + background-position: -273px 0; } .menu-icon-shutdown { - background-position: -294px 0px; + background-position: -294px 0; } .menu-icon-update { - background-position: -315px 0px; + background-position: -315px 0; } .menu-icon-viewlog-errors { - background-position: -336px 0px; + background-position: -336px 0; } .menu-icon-viewlog { - background-position: -357px 0px; + background-position: -357px 0; } .menu-icon-xbmc { - background-position: -378px 0px; + background-position: -378px 0; } .menu-icon-help { - background-position: -399px 0px; + background-position: -399px 0; } [class^="submenu-icon-"], [class*=" submenu-icon-"] { @@ -448,27 +451,27 @@ inc_top.tmpl } .submenu-icon-anime { - background-position: -21px 0px; + background-position: -21px 0; } .submenu-icon-bittorrent { - background-position: -84px 0px; + background-position: -84px 0; } .submenu-icon-failed-download { - background-position: -147px 0px; + background-position: -147px 0; } .submenu-icon-restart { - background-position: -273px 0px; + background-position: -273px 0; } .submenu-icon-shutdown { - background-position: -294px 0px; + background-position: -294px 0; } .submenu-icon-xbmc { - background-position: -378px 0px; + background-position: -378px 0; } /* ======================================================================= @@ -626,26 +629,26 @@ home.tmpl } .show .ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { - border-bottom-right-radius: 0px; + border-bottom-right-radius: 0; } .show .ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { - border-bottom-left-radius: 0px; + border-bottom-left-radius: 0; } .show .ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { - border-top-right-radius: 0px; + border-top-right-radius: 0; } .show .ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { - border-top-left-radius: 0px; + border-top-left-radius: 0; } .show .ui-widget-content { border-top: 1px solid #111; border-bottom: 1px solid #111; - border-left: 0px; - border-right: 0px; + border-left: 0; + border-right: 0; } .ui-progressbar .ui-progressbar-value { height:20px @@ -661,19 +664,19 @@ home.tmpl } .show .progress-80 { - border-radius: 0px; + border-radius: 0; } .show .progress-60 { - border-radius: 0px; + border-radius: 0; } .show .progress-40 { - border-radius: 0px; + border-radius: 0; } .show .progress-20 { - border-radius: 0px; + border-radius: 0; } .show-title { @@ -681,7 +684,7 @@ home.tmpl overflow: hidden; white-space: nowrap; font-size: 11px; - margin: 4px 4px 0px 4px; + margin: 4px 4px 0 4px; } .show-title:after { @@ -704,7 +707,7 @@ home.tmpl overflow: hidden; white-space: nowrap; font-size: 11px; - margin: 0px 4px 4px 4px; + margin: 0 4px 4px 4px; } .show-date:after { @@ -791,34 +794,27 @@ home_addShows.tmpl ========================================================================== */ #addShowPortal { - width: 750px; + width: 748px; padding: 10px 0; margin-right: auto; margin-left: auto; } #addShowPortal a { -/* padding: 10px;*/ - padding: 0px 20px; + padding: 0 20px; width: 360px; - float: left; - margin: 0 15px 15px 0; + margin: 0 7px 14px; } div.button { display: table-cell; vertical-align: middle; -/* padding-left: 10px;*/ } div.buttontext { display: table-cell; -/* - padding-left: 20px; - padding: 10px 15px; -*/ - padding: 10px 0px 10px 15px; + padding: 10px 0 10px 15px; text-align: left; white-space: normal; } @@ -826,7 +822,7 @@ div.buttontext p { margin: 0 } div.buttontext h3 { - margin-top: 0px; + margin-top: 0; } div.buttontext p { @@ -970,7 +966,6 @@ home_trendingShows.tmpl white-space: nowrap; font-size: 12px; overflow: hidden; -/* text-shadow: 1px 1px 0px #000;*/ padding-left: 4px; margin: 0; } @@ -1104,7 +1099,7 @@ ul.tags li { border: 1px solid #111; color: #FFF; font: 14px/18px "Open Sans", "Helvetica Neue", Helvetica, Arial, Geneva, sans-serif; - text-shadow: 0px 1px rgba(0, 0, 0, 0.8); + text-shadow: 0 1px rgba(0, 0, 0, 0.8); float: left; } @@ -1347,7 +1342,7 @@ td.col-search { } /* ======================================================================= -comingEpisodes.tmpl +episodeView.tmpl ========================================================================== */ .sort_data { @@ -1409,7 +1404,7 @@ h2.day, h2.network { letter-spacing: 1px; color: #FFF; text-align: center; - text-shadow: -1px -1px 0px rgba(0, 0, 0, 0.3); + text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.3); background-color: #333; } @@ -1418,7 +1413,7 @@ h2.day, h2.network { clear: both; border: 1px solid #ccc; margin: auto; - padding: 0px; + padding: 0; text-align: left; width: 750px; border-radius: 5px; @@ -1497,26 +1492,24 @@ h2.day, h2.network { vertical-align: middle; } -.calendarWrapper { +.daybydayWrapper { max-width: 1400px; margin: 0 auto; - padding: 0 3px + padding: 0 /*3px*/ } -.calendar-row { +.day-of-week { float: left; width: 14.28%; - padding: 0px 2px; + padding: 0 2px; } -.calendar-row .day-number { +.day-of-week .day-number { position: relative; height: 40px; - background-color: #333; - color: #fff; } -.calendar-row .day-number .number { +.day-of-week .day-number .number { position: absolute; right: 5px; font-weight: bold; @@ -1524,7 +1517,7 @@ h2.day, h2.network { line-height: 38px; } -.calendar-row .day-number .day { +.day-of-week .day-number .day { position: absolute; left: 5px; top: 3px; @@ -1532,33 +1525,21 @@ h2.day, h2.network { font-weight: bold; } -.calendar-row .day-number .month { +.day-of-week .day-number .month { position: absolute; left: 5px; bottom: 3px; text-transform: uppercase; } -.today .day-number .number, .today .day-number .month, .today .day-number .day { - color: #c7db40; -} - -.calendar-show { +.daybyday-show { margin-top: 4px; padding: 4px; width: 100% } -.odd .calendar-show { - background-color: #F5F1E4; -} - -.even .calendar-show { - background-color: #DFDACF; -} - -.calendar-row .poster img { - border: 1px solid #CCC; +.day-of-week .poster img { + border: 1px solid; border-radius: 5px; margin-bottom: 2px; display: block; @@ -1566,15 +1547,25 @@ h2.day, h2.network { margin-right: auto; } -.calendar-row .text .airtime, -.calendar-row .text .episode-title { +.day-of-week .text .airtime, +.day-of-week .text .episode { overflow: hidden; text-overflow: ellipsis; display: block; font-size: 12px; } -.calendar-row .episode-blank { +.day-of-week .text .episode .season, +.day-of-week .text .episode .number { + font-weight: 900; +} +.day-of-week .text .episode .season { + margin-right: 2px; +} +.day-of-week .text .episode .number { + margin-left: 2px; +} +.day-of-week .episode-blank { width: 250px; height: 32px; text-align: center; @@ -1918,7 +1909,7 @@ div.metadata_example label { line-height: 21px; display: block; padding: 3px; - margin: 0px; + margin: 0; } div.metadata_options input { margin-right: 3px; @@ -1931,7 +1922,7 @@ div.metadataDiv .disabled { .notifier-icon { float: left; - margin: 6px 4px 0px 0px; + margin: 6px 4px 0 0; } /* ======================================================================= @@ -1963,7 +1954,7 @@ td.tableright { text-align: left; vertical-align: middle; width: 225px; - padding: 6px 0px; + padding: 6px 0; } .optionWrapper div.selectChoices { @@ -1997,9 +1988,8 @@ Global ========================================================================== */ span.path { - padding: 3px 6px; - color: #8b0000; - background-color: #f5f1e4; + padding: 3px; + margin-left: 3px; } .align-left { @@ -2013,13 +2003,13 @@ span.path { span.quality { font: 12px/13px "Open Sans", verdana, sans-serif; - background-image:-webkit-linear-gradient(top, rgba(255,255,255,0.08),rgba(255,255,255,0) 50%,rgba(0,0,0,0) 50%,rgba(0,0,0,0.25)); - background-image:-moz-linear-gradient(top, rgba(255,255,255,0.08),rgba(255,255,255,0) 50%,rgba(0,0,0,0) 50%,rgba(0,0,0,0.25)); - background-image:-o-linear-gradient(top, rgba(255,255,255,0.08),rgba(255,255,255,0) 50%,rgba(0,0,0,0) 50%,rgba(0,0,0,0.25)); - background-image:linear-gradient(to bottom, rgba(255,255,255,0.08),rgba(255,255,255,0) 50%,rgba(0,0,0,0) 50%,rgba(0,0,0,0.25)); - -webkit-box-shadow:inset 0 1px rgba(255,255,255,0.1),inset 0 -1px 3px rgba(0,0,0,0.3),inset 0 0 0 1px rgba(255,255,255,0.08),0 1px 2px rgba(0,0,0,0.15); - box-shadow:inset 0 1px rgba(255,255,255,0.1),inset 0 -1px 3px rgba(0,0,0,0.3),inset 0 0 0 1px rgba(255,255,255,0.08),0 1px 2px rgba(0,0,0,0.15); - text-shadow: 0px 1px rgba(0, 0, 0, 0.8); + background-image:-webkit-linear-gradient(top, rgba(255, 255, 255, 0.08),rgba(255, 255, 255, 0) 50%,rgba(0, 0, 0, 0) 50%,rgba(0, 0, 0, 0.25)); + background-image:-moz-linear-gradient(top, rgba(255, 255, 255, 0.08),rgba(255, 255, 255, 0) 50%,rgba(0, 0, 0, 0) 50%,rgba(0, 0, 0, 0.25)); + background-image:-o-linear-gradient(top, rgba(255, 255, 255, 0.08),rgba(255, 255, 255, 0) 50%,rgba(0, 0, 0, 0) 50%,rgba(0, 0, 0, 0.25)); + background-image:linear-gradient(to bottom, rgba(255, 255, 255, 0.08),rgba(255, 255, 255, 0) 50%,rgba(0, 0, 0, 0) 50%,rgba(0, 0, 0, 0.25)); + -webkit-box-shadow:inset 0 1px rgba(255, 255, 255, 0.1),inset 0 -1px 3px rgba(0, 0, 0, 0.3),inset 0 0 0 1px rgba(255, 255, 255, 0.08),0 1px 2px rgba(0, 0, 0, 0.15); + box-shadow:inset 0 1px rgba(255, 255, 255, 0.1),inset 0 -1px 3px rgba(0, 0, 0, 0.3),inset 0 0 0 1px rgba(255, 255, 255, 0.08),0 1px 2px rgba(0, 0, 0, 0.15); + text-shadow: 0 1px rgba(0, 0, 0, 0.8); color: #FFFFFF; display: inline-block; padding: 2px 4px; @@ -2139,7 +2129,7 @@ div.blackwhitelist span { } div.blackwhitelist.anidb, div.blackwhitelist.manual { - margin: 7px 0px; + margin: 7px 0; } @@ -2159,12 +2149,12 @@ html * { } input[type="checkbox"] { - margin: 2px 0px 0px; + margin: 2px 0 0; line-height: normal; } input[type="radio"] { - margin: 2px 0px 0px; + margin: 2px 0 0; line-height: normal; } @@ -2179,7 +2169,7 @@ input, textarea, select, .uneditable-input { } .navbar-brand { - padding: 0px; + padding: 0; } /* navbar styling */ @@ -2306,7 +2296,7 @@ fieldset[disabled] .navbar-default .btn-link:focus { .dropdown-menu { background-color: #F5F1E4; border: 1px solid rgba(0, 0, 0, 0.15); - box-shadow: 0px 6px 12px rgba(0, 0, 0, 0.176); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.176); } .form-control { @@ -2863,7 +2853,7 @@ div.formpaginate .prev, div.formpaginate .next { .stepDiv.parent-folder { padding: 15px 0 0; width: 430px; - margin: 0px auto; + margin: 0 auto; } .stepDiv .nocheck { @@ -2985,7 +2975,7 @@ thead.tablesorter-stickyHeader { .tablesorter tfoot tr { color: #fff; text-align: center; - text-shadow: -1px -1px 0 rgba(0,0,0,0.3); + text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.3); background-color: #333; border-collapse: collapse; } @@ -3205,6 +3195,10 @@ span.token-input-delete-token { .time-am-pm { margin-left: 2px; } +#content.episodeview-banner .time-am-pm, +#content.episodeview-poster .time-am-pm { + margin-left: 0; +} /* ======================================================================= jquery.confirm.css @@ -3217,8 +3211,8 @@ jquery.confirm.css top: 0; left: 0; 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); + 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; } @@ -3230,7 +3224,7 @@ jquery.confirm.css top: 50%; margin: -130px 0 0 -230px; border: 1px solid #111; - box-shadow: 0px 0px 12px 0px rgba(0, 0, 0, 0.175); + box-shadow: 0 0 12px 0 rgba(0, 0, 0, 0.175); } #confirmBox h1, @@ -3265,7 +3259,7 @@ jquery.confirm.css display: inline-block; color: #fff; text-align:center; - text-shadow: 0px 1px 1px rgba(0, 0, 0, 0.75); + text-shadow: 0 1px 1px rgba(0, 0, 0, 0.75); background-clip: padding-box; border: 1px solid #111; border-radius: 3px; @@ -3273,12 +3267,12 @@ jquery.confirm.css -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; - background-image: -webkit-linear-gradient(top, rgba(255,255,255,0.08),rgba(255,255,255,0) 50%,rgba(0,0,0,0) 51%,rgba(0,0,0,0.25)); - background-image: -moz-linear-gradient(top, rgba(255,255,255,0.08),rgba(255,255,255,0) 50%,rgba(0,0,0,0) 51%,rgba(0,0,0,0.25)); - background-image: -o-linear-gradient(top, rgba(255,255,255,0.08),rgba(255,255,255,0) 50%,rgba(0,0,0,0) 51%,rgba(0,0,0,0.25)); - background-image: linear-gradient(to bottom, rgba(255,255,255,0.08),rgba(255,255,255,0) 50%,rgba(0,0,0,0) 51%,rgba(0,0,0,0.25)); - -webkit-box-shadow: inset 0 1px rgba(255,255,255,0.1),inset 0 -1px 3px rgba(0,0,0,0.3),inset 0 0 0 1px rgba(255,255,255,0.08),0 1px 2px rgba(0,0,0,0.15); - box-shadow: inset 0 1px rgba(255,255,255,0.1),inset 0 -1px 3px rgba(0,0,0,0.3),inset 0 0 0 1px rgba(255,255,255,0.08),0 1px 2px rgba(0,0,0,0.15); + background-image: -webkit-linear-gradient(top, rgba(255, 255, 255, 0.08),rgba(255, 255, 255, 0) 50%,rgba(0, 0, 0, 0) 51%,rgba(0, 0, 0, 0.25)); + background-image: -moz-linear-gradient(top, rgba(255, 255, 255, 0.08),rgba(255, 255, 255, 0) 50%,rgba(0, 0, 0, 0) 51%,rgba(0, 0, 0, 0.25)); + background-image: -o-linear-gradient(top, rgba(255, 255, 255, 0.08),rgba(255, 255, 255, 0) 50%,rgba(0, 0, 0, 0) 51%,rgba(0, 0, 0, 0.25)); + background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0.08),rgba(255, 255, 255, 0) 50%,rgba(0, 0, 0, 0) 51%,rgba(0, 0, 0, 0.25)); + -webkit-box-shadow: inset 0 1px rgba(255, 255, 255, 0.1),inset 0 -1px 3px rgba(0, 0, 0, 0.3),inset 0 0 0 1px rgba(255, 255, 255, 0.08),0 1px 2px rgba(0, 0, 0, 0.15); + box-shadow: inset 0 1px rgba(255, 255, 255, 0.1),inset 0 -1px 3px rgba(0, 0, 0, 0.3),inset 0 0 0 1px rgba(255, 255, 255, 0.08),0 1px 2px rgba(0, 0, 0, 0.15); } #confirmBox .button:last-child { diff --git a/gui/slick/interfaces/default/apiBuilder.tmpl b/gui/slick/interfaces/default/apiBuilder.tmpl index 43cfd914..c169fe2d 100644 --- a/gui/slick/interfaces/default/apiBuilder.tmpl +++ b/gui/slick/interfaces/default/apiBuilder.tmpl @@ -90,8 +90,8 @@ addOption("postprocess", "process_method", "&process_method=copy"); addOption("postprocess", "type", "&type=manual") addOption("sb.setdefaults", "Optional Param", "", 1); -addList("sb.setdefaults", "Exclude Paused Shows on ComingEps", "&future_show_paused=0", "sb.setdefaults-status"); -addList("sb.setdefaults", "Include Paused Shows on ComingEps", "&future_show_paused=1", "sb.setdefaults-status"); +addList("sb.setdefaults", "Exclude Paused Shows on EpisodeView", "&future_show_paused=0", "sb.setdefaults-status"); +addList("sb.setdefaults", "Include Paused Shows on EpisodeView", "&future_show_paused=1", "sb.setdefaults-status"); addOption("sb.setdefaults-status", "Optional Param", "", 1); addList("sb.setdefaults-status", "Wanted", "&status=wanted", "sb.setdefaults-opt"); diff --git a/gui/slick/interfaces/default/comingEpisodes.tmpl b/gui/slick/interfaces/default/comingEpisodes.tmpl deleted file mode 100644 index f10003b4..00000000 --- a/gui/slick/interfaces/default/comingEpisodes.tmpl +++ /dev/null @@ -1,626 +0,0 @@ -#import sickbeard -#import datetime -#from sickbeard.common import * -#from sickbeard import sbdatetime -#from sickbeard.helpers import anon_url - -#set global $title = 'Coming Episodes' -#set global $header = 'Coming Episodes' - -#set global $sbPath = '..' - -#set global $topmenu = 'comingEpisodes' -#import os.path -#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_top.tmpl') -#set $sort = $sickbeard.COMING_EPS_SORT -<script type="text/javascript" src="$sbRoot/js/ajaxEpSearch.js?$sbPID"></script> -#if $varExists('header') - <h1 class="header">$header</h1> -#else - <h1 class="title">$title</h1> -#end if - -<script type="text/javascript" charset="utf-8"> -<!-- -\$(document).ready(function(){ - - var \$container = [\$('#day0'), \$('#day1'), \$('#day2'), \$('#day3'), \$('#day4'), \$('#day5'), \$('#day6')]; - - jQuery.each(\$container, function (j) { - this.isotope({ - itemSelector: '.calendar-show', - sortBy : '$sickbeard.COMING_EPS_SORT', - layoutMode: 'vertical', - transitionDuration: 0, - getSortData: { - show: function( itemElem ) { - var name = \$( itemElem ).attr('data-name'); - #if not $sickbeard.SORT_ARTICLE: - return (name || '').replace(/^(?:(?:A(?!\s+to)n?)|The)\s(\w)/i, '$1'); - #else: - return (name || ''); - #end if - }, - network: '[data-network]', - date: function( itemElem ) { - var date = \$( itemElem ).attr('data-date'); - return date.length && parseInt( date, 10 ); - } - } - }); - }); - - imagesLoaded( '.calendar-show', function() { - jQuery.each(\$container, function (j) { - this.isotope('layout'); - }); - }); - - \$('#sort').on( 'change', function() { - var sortValue = this.value; - jQuery.each(\$container, function (j) { - this.isotope({ sortBy: sortValue }); - }); - \$.get(this.options[this.selectedIndex].getAttribute('data-sort')); - }); - -}); -//--> -</script> - -<style type="text/css"> -#SubMenu {display:none} -#contentWrapper {padding-top:30px} -</style> - -<div class="h2footer pull-right"> - <span>Layout: - <select name="layout" class="form-control form-control-inline input-sm" onchange="location = this.options[this.selectedIndex].value;"> - <option value="$sbRoot/setComingEpsLayout/?layout=poster" #if 'poster' == $sickbeard.COMING_EPS_LAYOUT then 'selected="selected"' else ''#>Poster</option> - <option value="$sbRoot/setComingEpsLayout/?layout=calendar" #if 'calendar' == $sickbeard.COMING_EPS_LAYOUT then 'selected="selected"' else ''#>Calendar</option> - <option value="$sbRoot/setComingEpsLayout/?layout=banner" #if 'banner' == $sickbeard.COMING_EPS_LAYOUT then 'selected="selected"' else ''#>Banner</option> - <option value="$sbRoot/setComingEpsLayout/?layout=list" #if 'list' == $sickbeard.COMING_EPS_LAYOUT then 'selected="selected"' else ''#>List</option> - </select> - </span> -   -#if 'calendar' != $layout: - <span>Sort By: - <select name="sort" class="form-control form-control-inline input-sm" onchange="location = this.options[this.selectedIndex].value;"> - <option value="$sbRoot/setComingEpsSort/?sort=date" #if 'date' == $sickbeard.COMING_EPS_SORT then 'selected="selected"' else ''#>Date</option> - <option value="$sbRoot/setComingEpsSort/?sort=network" #if 'network' == $sickbeard.COMING_EPS_SORT then 'selected="selected"' else ''#>Network</option> - <option value="$sbRoot/setComingEpsSort/?sort=show" #if 'show' == $sickbeard.COMING_EPS_SORT then 'selected="selected"' else ''#>Show</option> - </select> - </span> -   -#else - <span>Sort By: - <select name="sort" id="sort" class="form-control form-control-inline input-sm"> - <option value="date" data-sort="$sbRoot/setComingEpsSort/?sort=date" #if 'date' == $sickbeard.COMING_EPS_SORT then 'selected="selected"' else ''#>Date</option> - <option value="network" data-sort="$sbRoot/setComingEpsSort/?sort=network" #if 'network' == $sickbeard.COMING_EPS_SORT then 'selected="selected"' else ''#>Network</option> - <option value="show" data-sort="$sbRoot/setComingEpsSort/?sort=show" #if 'show' == $sickbeard.COMING_EPS_SORT then 'selected="selected"' else ''#>Show</option> - </select> - </span> -   -#end if - <span>View Paused: - <select name="viewpaused" class="form-control form-control-inline input-sm" onchange="location = this.options[this.selectedIndex].value;"> - <option value="$sbRoot/toggleComingEpsDisplayPaused"<%= (' selected="selected"', '')[True == sickbeard.COMING_EPS_DISPLAY_PAUSED] %>>Hidden</option> - <option value="$sbRoot/toggleComingEpsDisplayPaused"<%= ('', ' selected="selected"')[True == sickbeard.COMING_EPS_DISPLAY_PAUSED] %>>Shown</option> - </select> - </span> -</div> - -<div class="key pull-right"> -#if 'calendar' != $layout: - <b>Key:</b> - <span class="listing-key listing-overdue">Missed</span> - <span class="listing-key listing-current">Current</span> - <span class="listing-key listing-default">Future</span> - <span class="listing-key listing-toofar">Distant</span> -#end if - <a class="btn btn-inline forceBacklog" href="webcal://$sbHost:$sbHttpPort/calendar"> - <i class="icon-calendar icon-white"></i>Subscribe</a> -</div> - -<br> - -#if 'list' == $layout: -<!-- start list view //--> - -<script type="text/javascript" src="$sbRoot/js/plotTooltip.js?$sbPID"></script> -<script type="text/javascript" charset="utf-8"> -<!-- -\$.tablesorter.addParser({ - id: 'loadingNames', - is: function(s) { - return false - }, - format: function(s) { - if (0 == s.indexOf('Loading...')) - return s.replace('Loading...', '000') -#if not $sickbeard.SORT_ARTICLE: - return (s || '').replace(/^(?:(?:A(?!\s+to)n?)|The)\s(\w)/i, '$1') -#else: - return (s || '') -#end if - }, - type: 'text' -}); -\$.tablesorter.addParser({ - id: 'quality', - is: function(s) { - return false - }, - format: function(s) { - return s.replace('hd1080p', 5).replace('hd720p', 4).replace('hd', 3).replace('sd', 2).replace('any', 1).replace('best', 0).replace('custom', 7) - }, - type: 'numeric' -}); -\$.tablesorter.addParser({ - id: 'cDate', - is: function(s) { - return false - }, - format: function(s) { - return s - }, - type: 'numeric' -}); - -\$(document).ready(function(){ - -#set $sort_codes = {'date': 0, 'show': 1, 'network': 4} -#if $sort not in $sort_codes: - $sort = 'date' -#end if - - sortList = [[$sort_codes[$sort], 0]]; - - \$('#showListTable:has(tbody tr)').tablesorter({ - widgets: ['stickyHeaders'], - sortList: sortList, - textExtraction: { - 0: function(node) { return \$(node).find('span').text().toLowerCase() }, - 4: function(node) { return \$(node).find('img').attr('alt') }, - 5: function(node) { return \$(node).find('span').text().toLowerCase() } - }, - headers: { - 0: { sorter: 'cDate' }, - 1: { sorter: 'loadingNames' }, - 2: { sorter: false }, - 3: { sorter: false }, - 4: { sorter: 'loadingNames' }, - 5: { sorter: 'quality' }, - 6: { sorter: false }, - 7: { sorter: false }, - 8: { sorter: false } - } - }); - - \$('#sbRoot').ajaxEpSearch(); - - #set $fuzzydate = 'airdate' - #if $sickbeard.FUZZY_DATING: - fuzzyMoment({ - containerClass : '.${fuzzydate}', - dateHasTime : true, - dateFormat : '${sickbeard.DATE_PRESET}', - timeFormat : '${sickbeard.TIME_PRESET}', - trimZero : #if $sickbeard.TRIM_ZERO then 'true' else 'false'# - }); - #end if - -}); -//--> -</script> - -#set $show_div = 'listing-default' - -<input type="hidden" id="sbRoot" value="$sbRoot" /> - -<table id="showListTable" class="sickbeardTable tablesorter seasonstyle" cellspacing="1" border="0" cellpadding="0"> - - <thead> - <tr> - <th>Airdate</th> - <th>Show</th> - <th class="nowrap">Next Ep</th> - <th>Next Ep Name</th> - <th>Network</th> - <th>Quality</th> - <th>Indexers</th> - <th>Search</th> - </tr> - </thead> - - <tbody style="text-shadow:none;"> - -#for $cur_result in $sql_results: - #set $cur_indexer = int($cur_result['indexer']) - #set $runtime = $cur_result['runtime'] - - #if int($cur_result['paused']) and not $sickbeard.COMING_EPS_DISPLAY_PAUSED: - #continue - #end if - - #set $cur_ep_airdate = $cur_result['localtime'].date() - - #if $runtime: - #set $cur_ep_enddate = $cur_result['localtime'] + datetime.timedelta(minutes = $runtime) - #if $cur_ep_enddate < $today: - #set $show_div = 'listing-overdue' - #elif $cur_ep_airdate >= $next_week.date(): - #set $show_div = 'listing-toofar' - #elif $cur_ep_airdate >= $today.date() and $cur_ep_airdate < $next_week.date(): - #if $cur_ep_airdate == $today.date(): - #set $show_div = 'listing-current' - #else: - #set $show_div = 'listing-default' - #end if - #end if - #end if - - <!-- start $cur_result['show_name'] //--> - <tr class="$show_div"> - ## forced to use a div to wrap airdate, the column sort went crazy with a span - <td align="center" class="nowrap"> - <div class="${fuzzydate}">$sbdatetime.sbdatetime.sbfdatetime($cur_result['localtime']).decode($sickbeard.SYS_ENCODING)</div><span class="sort_data">$time.mktime($cur_result['localtime'].timetuple())</span> - </td> - - <td class="tvShow"><a href="$sbRoot/home/displayShow?show=${cur_result['showid']}">$cur_result['show_name']</a> -#if int($cur_result['paused']): - <span class="pause">[paused]</span> -#end if - </td> - - <td class="nowrap" align="center"> - <%= 'S%02iE%02i' % (int(cur_result['season']), int(cur_result['episode'])) %> - </td> - - <td> -#if $cur_result['description']: - <img alt='' src='$sbRoot/images/info32.png' height='16' width='16' class='plotInfo' id="plot_info_<%= '%s_%s_%s' % (str(cur_result['showid']), str(cur_result['season']), str(cur_result['episode'])) %>" /> -#else: - <img alt="" src="$sbRoot/images/info32.png" width="16" height="16" class="plotInfoNone" /> -#end if - $cur_result['name'] - </td> - - <td align="center"> - $cur_result['network'] - </td> - - <td align="center"> -#if int($cur_result['quality']) in $qualityPresets: - <span class="quality $qualityPresetStrings[int($cur_result['quality'])]">$qualityPresetStrings[int($cur_result['quality'])]</span> -#else: - <span class="quality Custom">Custom</span> -#end if - </td> - - <td align="center" style="vertical-align: middle;"> -#if $cur_result['imdb_id']: - <a href="<%= anon_url('http://www.imdb.com/title/', cur_result['imdb_id']) %>" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false" title="http://www.imdb.com/title/${cur_result['imdb_id']}"><img alt="[imdb]" height="16" width="16" src="$sbRoot/images/imdb.png" /> -#end if - <a href="<%= anon_url(sickbeard.indexerApi(cur_indexer).config['show_url'], cur_result['showid']) %>" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false" title="$sickbeard.indexerApi($cur_indexer).config['show_url']${cur_result['showid']}"><img alt="$sickbeard.indexerApi($cur_indexer).name" height="16" width="16" src="$sbRoot/images/$sickbeard.indexerApi($cur_indexer).config['icon']" /></a> - </td> - - <td align="center"> - <a href="$sbRoot/home/searchEpisode?show=${cur_result['showid']}&season=$cur_result['season']&episode=$cur_result['episode']" title="Manual Search" id="forceUpdate-${cur_result['showid']}" class="forceUpdate epSearch"><img alt="[search]" height="16" width="16" src="$sbRoot/images/search16.png" id="forceUpdateImage-${cur_result['showid']}" /></a> - </td> - </tr> - <!-- end $cur_result['show_name'] //--> -#end for - </tbody> - - <tfoot> - <tr> - <th rowspan="1" colspan="10" align="center"> </th> - </tr> - </tfoot> - -</table> -<!-- end list view //--> - - -#else if $layout in ['banner', 'poster']: - - -<!-- start non list view //--> -<script type="text/javascript" charset="utf-8"> -<!-- -\$(document).ready(function(){ - \$('#sbRoot').ajaxEpSearch({'size': 16, 'loadingImage': 'loading16' + themeSpinner + '.gif'}); - \$('.ep_summary').hide(); - \$('.ep_summaryTrigger').click(function() { - \$(this).next('.ep_summary').slideToggle('normal', function() { - \$(this).prev('.ep_summaryTrigger').attr('src', function(i, src) { - return \$(this).next('.ep_summary').is(':visible') ? src.replace('plus','minus') : src.replace('minus','plus') - }); - }); - }); - - #set $fuzzydate = 'airdate' - #if $sickbeard.FUZZY_DATING: - fuzzyMoment({ - dtInline : true, - dtGlue : ' at ', - containerClass : '.${fuzzydate}', - dateHasTime : true, - dateFormat : '${sickbeard.DATE_PRESET}', - timeFormat : '${sickbeard.TIME_PRESET}', - trimZero : #if $sickbeard.TRIM_ZERO then 'true' else 'false'# - }); - #end if - -}); -//--> -</script> - -#set $cur_segment = None -#set $too_late_header = False -#set $missed_header = False -#set $today_header = False -#set $show_div = 'ep_listing listing-default' - -#if 'show' == $sort: - <br /><br /> -#end if - -#for $cur_result in $sql_results: - #set $cur_indexer = int($cur_result['indexer']) - -<!-- start $cur_result['show_name'] //--> - - #if int($cur_result['paused']) and not $sickbeard.COMING_EPS_DISPLAY_PAUSED: - #continue - #end if - - #set $runtime = $cur_result['runtime'] - - #if 'network' == $sort: - #set $show_network = $cur_result['network'] if $cur_result['network'] else 'no network' - #if $cur_segment != $show_network: - <div class="comingepheader"> - <br><h2 class="network">$show_network</h2> - #set $cur_segment = $cur_result['network'] - #end if - #set $cur_ep_airdate = $cur_result['localtime'].date() - - #if $runtime: - #set $cur_ep_enddate = $cur_result['localtime'] + datetime.timedelta(minutes = $runtime) - #if $cur_ep_enddate < $today: - #set $show_div = 'ep_listing listing-overdue' - #elif $cur_ep_airdate >= $next_week.date(): - #set $show_div = 'ep_listing listing-toofar' - #elif $cur_ep_enddate >= $today and $cur_ep_airdate < $next_week.date(): - #if $cur_ep_airdate == $today.date(): - #set $show_div = 'ep_listing listing-current' - #else: - #set $show_div = 'ep_listing listing-default' - #end if - #end if - #end if - - #elif 'date' == $sort: - #set $cur_ep_airdate = $cur_result['localtime'].date() - - #if $cur_segment != $cur_ep_airdate: - #if $runtime: - #set $cur_ep_enddate = $cur_result['localtime'] + datetime.timedelta(minutes = $runtime) - #if $cur_ep_enddate < $today and $cur_ep_airdate != $today.date() and not $missed_header: - <br /><h2 class="day">Missed</h2> - #set $missed_header = True - #elif $cur_ep_airdate >= $next_week.date() and not $too_late_header: - <br /><h2 class="day">Later</h2> - #set $too_late_header = True - #elif $cur_ep_enddate >= $today and $cur_ep_airdate < $next_week.date(): - #if $cur_ep_airdate == $today.date(): - <br /><h2 class="day">$sbdatetime.sbdatetime.sbfdate($cur_ep_airdate, '%A').decode($sickbeard.SYS_ENCODING).capitalize() <span style="font-size: 14px; vertical-align: top;">[Today]</span></h2> - #set $today_header = True - #else: - <br /><h2 class="day">$sbdatetime.sbdatetime.sbfdate($cur_ep_airdate, '%A').decode($sickbeard.SYS_ENCODING).capitalize()</h2> - #end if - #end if - #end if - #set $cur_segment = $cur_ep_airdate - #end if - - #if $cur_ep_airdate == $today.date() and not $today_header: - <div class="comingepheader"> - <br /><h2 class="day">$sbdatetime.sbdatetime.sbfdate($cur_ep_airdate, '%A').decode($sickbeard.SYS_ENCODING).capitalize() <span style="font-size: 14px; vertical-align: top;">[Today]</span></h2> - #set $today_header = True - #end if - #if $runtime: - #set $cur_ep_enddate = $cur_result['localtime'] + datetime.timedelta(minutes = $runtime) - #if $cur_ep_enddate < $today: - #set $show_div = 'ep_listing listing-overdue' - #elif $cur_ep_airdate >= $next_week.date(): - #set $show_div = 'ep_listing listing-toofar' - #elif $cur_ep_enddate >= $today and $cur_ep_airdate < $next_week.date(): - #if $cur_ep_airdate == $today.date(): - #set $show_div = 'ep_listing listing-current' - #else: - #set $show_div = 'ep_listing listing-default' - #end if - #end if - #end if - - #elif 'show' == $sort: - #set $cur_ep_airdate = $cur_result['localtime'].date() - - #if $runtime: - #set $cur_ep_enddate = $cur_result['localtime'] + datetime.timedelta(minutes = $runtime) - #if $cur_ep_enddate < $today: - #set $show_div = 'ep_listing listing-overdue listingradius' - #elif $cur_ep_airdate >= $next_week.date(): - #set $show_div = 'ep_listing listing-toofar listingradius' - #elif $cur_ep_enddate >= $today and $cur_ep_airdate < $next_week.date(): - #if $cur_ep_airdate == $today.date(): - #set $show_div = 'ep_listing listing-current listingradius' - #else: - #set $show_div = 'ep_listing listing-default listingradius' - #end if - #end if - #end if - #end if - -<div class="$show_div" id="listing-${cur_result['showid']}"> - <div class="tvshowDiv"> - <table width="100%" border="0" cellpadding="0" cellspacing="0"> - <tr> - <th #if 'banner' == $layout then 'class="nobg"' else 'rowspan="2"'# valign="top"> - <a href="$sbRoot/home/displayShow?show=${cur_result['showid']}"><img alt="" class="#if 'banner' == $layout then 'bannerThumb' else 'posterThumb'#" src="$sbRoot/showPoster/?show=${cur_result['showid']}&which=#if 'poster' == $layout then 'poster_thumb' else $layout#" /></a> - </th> -#if 'banner' == $layout: - </tr> - <tr> -#end if - - <td class="next_episode"> - <div class="clearfix"> - <span class="tvshowTitle"> - <a href="$sbRoot/home/displayShow?show=${cur_result['showid']}">$cur_result['show_name'] - #if int($cur_result['paused']): - <span class="pause">[paused]</span> - #end if - </a></span> - - <span class="tvshowTitleIcons"> -#if $cur_result['imdb_id']: - <a href="<%= anon_url('http://www.imdb.com/title/', cur_result['imdb_id']) %>" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false" title="http://www.imdb.com/title/${cur_result['imdb_id']}"><img alt="[imdb]" height="16" width="16" src="$sbRoot/images/imdb.png" /> -#end if - <a href="<%= anon_url(sickbeard.indexerApi(cur_indexer).config['show_url'], cur_result['showid']) %>" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false" title="$sickbeard.indexerApi($cur_indexer).config['show_url']${cur_result['showid']}"><img alt="$sickbeard.indexerApi($cur_indexer).name" height="16" width="16" src="$sbRoot/images/$sickbeard.indexerApi($cur_indexer).config['icon']" /></a> - <span><a href="$sbRoot/home/searchEpisode?show=${cur_result['showid']}&season=$cur_result['season']&episode=$cur_result['episode']" title="Manual Search" id="forceUpdate-${cur_result['showid']}" class="epSearch forceUpdate"><img alt="[search]" height="16" width="16" src="$sbRoot/images/search16.png" id="forceUpdateImage-${cur_result['showid']}" /></a></span> - </span> - </div> - - <span class="title">Next Episode:</span> <span><%= 'S%02iE%02i' % (int(cur_result['season']), int(cur_result['episode'])) %> - $cur_result['name']</span> - - <div class="clearfix"> - - <span class="title">Airs: </span><span class="${fuzzydate}">$sbdatetime.sbdatetime.sbfdatetime($cur_result['localtime']).decode($sickbeard.SYS_ENCODING)</span><%= ('', '<span> on %s</span>' % str(cur_result['network']))[None is not cur_result['network']] %> - </div> - - <div class="clearfix"> - <span class="title">Quality:</span> - #if int($cur_result['quality']) in $qualityPresets: - <span class="quality $qualityPresetStrings[int($cur_result['quality'])]">$qualityPresetStrings[int($cur_result['quality'])]</span> - #else: - <span class="quality Custom">Custom</span> - #end if - </div> - </td> - </tr> - <tr> - <td style="vertical-align: top;"> - <div> -#if $cur_result['description']: - <span class="title" style="vertical-align:middle;">Plot:</span> - <img class="ep_summaryTrigger" src="$sbRoot/images/plus.png" height="16" width="16" alt="" title="Toggle Summary" /><div class="ep_summary">$cur_result['description']</div> -#else: - <span class="title ep_summaryTriggerNone" style="vertical-align:middle;">Plot:</span> - <img class="ep_summaryTriggerNone" src="$sbRoot/images/plus.png" height="16" width="16" alt="" /> -#end if - </div> - </td> - </tr> - </table> - </div> -</div> - -<!-- end $cur_result['show_name'] //--> -#end for - -<!-- end non list view //--> -#end if - -#if 'calendar' == $layout: - -#set $today = datetime.date.today() -#set $dates = [$today + datetime.timedelta(days = $i) for $i in range(7)] -#set $tbl_day = 0 -<br> -<br> -<div class="calendarWrapper"> -<input type="hidden" id="sbRoot" value="$sbRoot" /> - #for $day in $dates - #set $tbl_day += 1 - - #if $tbl_day == 1 - #set $showtoday = 'today' - #else - #set $showtoday = '' - #end if - - <div class="calendar-row $showtoday <%= '%s' % (('even', 'odd')[1 == tbl_day % 2]) %>"> - <div class="day-number"> - <div class="number">$sbdatetime.sbdatetime.sbfdate($day, ' %d').decode($sickbeard.SYS_ENCODING).replace(' 0', ' ')</div> - <div class="day"> - <span class="visible-lg">$sbdatetime.sbdatetime.sbfdate($day, '%A').decode($sickbeard.SYS_ENCODING).capitalize()</span> - <span class="hidden-lg">$sbdatetime.sbdatetime.sbfdate($day, '%a').decode($sickbeard.SYS_ENCODING).capitalize()</span> - </div> - <div class="month"> - <span class="visible-lg">$sbdatetime.sbdatetime.sbfdate($day, '%B').decode($sickbeard.SYS_ENCODING).capitalize()</span> - <span class="hidden-lg">$sbdatetime.sbdatetime.sbfdate($day, '%b').decode($sickbeard.SYS_ENCODING).capitalize()</span> - </div> - </div> - <div id="$sbdatetime.sbdatetime.sbfdate($day, 'day%w')"> - - #set $day_has_show = False - #for $cur_result in $sql_results: - #if int($cur_result['paused']) and not $sickbeard.COMING_EPS_DISPLAY_PAUSED: - #continue - #end if - - #set $cur_indexer = int($cur_result['indexer']) - #set $runtime = $cur_result['runtime'] - #set $airday = $cur_result['localtime'].date() - - #if $airday == $day: - #set $day_has_show = True - #set $airtime = $sbdatetime.sbdatetime.sbftime($cur_result['localtime']).decode($sickbeard.SYS_ENCODING) - - #if $sickbeard.TRIM_ZERO: - #set $airtime = re.sub(r'0(\d:\d\d)', r'\1', $airtime, 0, re.IGNORECASE | re.MULTILINE) - #end if - - <div id="show-$cur_result['showid']" class="calendar-show" data-name="$cur_result['show_name']" data-network="$cur_result['network']" data-date="$time.mktime($cur_result['localtime'].timetuple())"> - <div class="poster"> - <a title="${cur_result['show_name']}" href="$sbRoot/home/displayShow?show=${cur_result['showid']}"><img class="img-responsive" alt="" src="$sbRoot/showPoster/?show=${cur_result['showid']}&which=poster_thumb" /></a> - </div> - <div class="text"> - <div class="episode-title" title="$cur_result['name']"> - <%= 'S%02iE%02i' % (int(cur_result['season']), int(cur_result['episode'])) %> - $cur_result['name'] - </div> - <div class="airtime"> - ${airtime} on $cur_result["network"] - </div> - </div> - </div><!-- end show-$cur_result['showid'] //--> - - #end if - - #end for - #if not $day_has_show: - - <div class="calendar-show" data-date="0"> - <span class="episode-blank">No shows for this day</span> - </div> - #end if - </div> - </div> - #end for - -<!-- end calender view //--> -#end if - -<div class="clearfix"></div> - -<script type="text/javascript" charset="utf-8"> -<!-- -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') diff --git a/gui/slick/interfaces/default/config_general.tmpl b/gui/slick/interfaces/default/config_general.tmpl index 410410c1..b375636c 100644 --- a/gui/slick/interfaces/default/config_general.tmpl +++ b/gui/slick/interfaces/default/config_general.tmpl @@ -570,7 +570,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 class="boldest">All non-absolute folder locations are relative to <span class="path">$sickbeard.DATA_DIR</span></b></h6> <input type="submit" class="btn pull-left config_submitter button" value="Save Changes" /> </div><!-- /config-components --> diff --git a/gui/slick/interfaces/default/episodeView.tmpl b/gui/slick/interfaces/default/episodeView.tmpl new file mode 100644 index 00000000..f3d8fe7f --- /dev/null +++ b/gui/slick/interfaces/default/episodeView.tmpl @@ -0,0 +1,695 @@ +#import sickbeard +#import datetime +#from sickbeard.common import * +#from sickbeard import sbdatetime +#from sickbeard.helpers import anon_url + +#set global $title = 'Episode View' +#set global $header = 'Episode View' + +#set global $sbPath = '..' + +#set global $topmenu = 'episodeView' +#import os.path +#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_top.tmpl') + +#set $sort = $sickbeard.EPISODE_VIEW_SORT +#set $table_sort_header_codes = {'time': 0, 'show': 1, 'network': 4} +#if $sort not in $table_sort_header_codes: + #set $sort = 'time' +#end if + +#if 'daybyday' != $layout: +<script type="text/javascript" src="$sbRoot/js/ajaxEpSearch.js?$sbPID"></script> +#end if + +#if $varExists('header') + <h1 class="header">$header</h1> +#else + <h1 class="title">$title</h1> +#end if + +#if 'daybyday' == $layout: +<script type="text/javascript" src="$sbRoot/js/plotTooltip.js?$sbPID"></script> +<script type="text/javascript" charset="utf-8"> +<!-- + \$(document).ready(function(){ + + var \$container = []; + \$.each(\$('[id^=day]'), function(){\$container.push(\$('#' + \$(this).attr('id')))}); + + jQuery.each(\$container, function(j) { + this.isotope({ + itemSelector: '.daybyday-show', + sortBy : '$sort', + layoutMode: 'vertical', + transitionDuration: 0, + getSortData: { + network: function(itemElem) { + return \$(itemElem).attr('data-network') || ''; + }, + showname: function(itemElem) { + return \$(itemElem).attr('data-name') || ''; + }, + season: function(itemElem) { + var season = \$(itemElem).attr('data-season') || '0'; + return season.length && parseInt(season, 10); + }, + episode: function(itemElem) { + var episode = \$(itemElem).attr('data-episode') || '0'; + return episode.length && parseInt(episode, 10); + }, + time: function(itemElem) { + var time = \$(itemElem).attr('data-time') || '0'; + return time.length && parseInt(time, 10); + } + } + }); + }); + + imagesLoaded('.daybyday-show', function() { + jQuery.each(\$container, function(j) { + this.isotope('layout'); + }); + }); + + var uiSortBy = (function(sortBy) { + var sortCriteria; + switch (sortBy) { + case 'network': + sortCriteria = ['network', 'time', 'showname', 'season', 'episode']; + break; + case 'show': + sortCriteria = ['showname', 'time', 'season', 'episode']; + break; + case 'time': + default: + sortCriteria = ['time', 'showname', 'season', 'episode']; + break; + } + jQuery.each(\$container, function(j) { + this.isotope({ + sortBy: sortCriteria, + sortAscending: 'asc' == \$('#sort-dir').attr('data-sort-dir') + }); + }); + }); + + \$('#sort').on('change', function() { + uiSortBy(this.value); + \$.get(this.options[this.selectedIndex].getAttribute('data-sort')); + }); + + \$('#sort-dir').on('click', function() { + var sortdir = \$(this).attr('data-sort-dir'), + newdir = ('asc' == sortdir ? 'desc' : 'asc'); + \$(this).attr('data-sort-dir', newdir); + \$(this).attr('title', 'Click to sort ' + sortdir + 'ending'); + \$(this).removeClass(sortdir).addClass(newdir); + uiSortBy(\$('#sort').val()); + }); + }); +//--> +</script> +#end if + +<style type="text/css"> +#SubMenu {display:none} +#if 'daybyday' == $layout: +.caret { + cursor: pointer; + vertical-align: middle; + margin-right: 2px; +} +.asc { + border-top: 0; + border-bottom: 8px solid; +} +.desc { + border-top: 8px solid; + border-bottom: 0; +} +#end if +</style> + +<div class="h2footer pull-right"> + <span>Layout: + <select name="layout" class="form-control form-control-inline input-sm" onchange="location = this.options[this.selectedIndex].value;"> + <option value="$sbRoot/setEpisodeViewLayout/?layout=banner" #if 'banner' == $sickbeard.EPISODE_VIEW_LAYOUT then 'selected="selected"' else ''#>Banner</option> + <option value="$sbRoot/setEpisodeViewLayout/?layout=daybyday" #if 'daybyday' == $sickbeard.EPISODE_VIEW_LAYOUT then 'selected="selected"' else ''#>Day by Day</option> + <option value="$sbRoot/setEpisodeViewLayout/?layout=list" #if 'list' == $sickbeard.EPISODE_VIEW_LAYOUT then 'selected="selected"' else ''#>List</option> + <option value="$sbRoot/setEpisodeViewLayout/?layout=poster" #if 'poster' == $sickbeard.EPISODE_VIEW_LAYOUT then 'selected="selected"' else ''#>Poster</option> + </select> + </span> +   + <span>Sort +#if 'daybyday' == $layout: + <span id="sort-dir" data-sort-dir="asc" class="caret asc" title="Click to sort descending"> </span> +#end if + By +#if 'daybyday' == $layout: + <select name="sort" id="sort" class="form-control form-control-inline input-sm"> + <option value="network" data-sort="$sbRoot/setEpisodeViewSort/?sort=network&redir=0" #if 'network' == $sort then 'selected="selected"' else ''#>Network</option> + <option value="show" data-sort="$sbRoot/setEpisodeViewSort/?sort=show&redir=0" #if 'show' == $sort then 'selected="selected"' else ''#>Show</option> + <option value="time" data-sort="$sbRoot/setEpisodeViewSort/?sort=time&redir=0" #if 'time' == $sort then 'selected="selected"' else ''#>Time</option> +#else + <select name="sort" class="form-control form-control-inline input-sm" onchange="location = this.options[this.selectedIndex].value;"> + <option value="$sbRoot/setEpisodeViewSort/?sort=time" #if 'time' == $sort then 'selected="selected"' else ''#>Date/Time</option> + <option value="$sbRoot/setEpisodeViewSort/?sort=network" #if 'network' == $sort then 'selected="selected"' else ''#>Network</option> + <option value="$sbRoot/setEpisodeViewSort/?sort=show" #if 'show' == $sort then 'selected="selected"' else ''#>Show</option> +#end if + </select> + </span> +   + <span>View Paused: + <select name="viewpaused" class="form-control form-control-inline input-sm" onchange="location = this.options[this.selectedIndex].value;"> + <option value="$sbRoot/toggleEpisodeViewDisplayPaused"<%= (' selected="selected"', '')[True == sickbeard.EPISODE_VIEW_DISPLAY_PAUSED] %>>Hidden</option> + <option value="$sbRoot/toggleEpisodeViewDisplayPaused"<%= ('', ' selected="selected"')[True == sickbeard.EPISODE_VIEW_DISPLAY_PAUSED] %>>Shown</option> + </select> + </span> +</div> + +<div class="key pull-right"> +#if 'daybyday' != $layout: + <b>Key:</b> + <span class="listing-key listing-overdue">Missed</span> + <span class="listing-key listing-current">Current</span> + <span class="listing-key listing-default">Future</span> + <span class="listing-key listing-toofar">Distant</span> +#end if + <a class="btn btn-inline forceBacklog" href="webcal://$sbHost:$sbHttpPort/calendar"> + <i class="icon-calendar icon-white"></i>Subscribe</a> +</div> + +<br> + + + +#if 'list' == $layout: +<!-- start list view //--> + +<script type="text/javascript" src="$sbRoot/js/plotTooltip.js?$sbPID"></script> +<script type="text/javascript" charset="utf-8"> +<!-- + \$.tablesorter.addParser({ + id: 'loadingNames', + is: function(s) { + return false + }, + format: function(s) { + if(0 == s.indexOf('Loading...')) + return s.replace('Loading...', '000') + return (s || '') + }, + type: 'text' + }); + \$.tablesorter.addParser({ + id: 'quality', + is: function(s) { + return false + }, + format: function(s) { + return s.replace('hd1080p', 5).replace('hd720p', 4).replace('hd', 3).replace('sd', 2).replace('any', 1).replace('best', 0).replace('custom', 7) + }, + type: 'numeric' + }); + \$.tablesorter.addParser({ + id: 'cDate', + is: function(s) { + return false + }, + format: function(s) { + return s + }, + type: 'numeric' + }); + + \$(document).ready(function(){ + + sortList = [[$table_sort_header_codes[$sort], 0]]; + + \$('#showListTable:has(tbody tr)').tablesorter({ + widgets: ['stickyHeaders'], + sortList: sortList, + textExtraction: { + 0: function(node) {return \$(node).find('span').text().toLowerCase() || ''}, + 1: function(node) {return \$(node).find('a').attr('data-name') || ''}, + 4: function(node) {return \$(node).find('span').attr('data-network') || ''}, + 5: function(node) {return \$(node).find('span').text().toLowerCase() || ''} + }, + headers: { + 0: {sorter: 'cDate'}, + 1: {sorter: 'loadingNames'}, + 2: {sorter: false}, + 3: {sorter: false}, + 4: {sorter: 'loadingNames'}, + 5: {sorter: 'quality'}, + 6: {sorter: false}, + 7: {sorter: false}, + 8: {sorter: false} + } + }); + + \$('#sbRoot').ajaxEpSearch(); + + #set $fuzzydate = 'airdate' + #if $sickbeard.FUZZY_DATING: + fuzzyMoment({ + containerClass : '.${fuzzydate}', + dateHasTime : true, + dateFormat : '${sickbeard.DATE_PRESET}', + timeFormat : '${sickbeard.TIME_PRESET}', + trimZero : #if $sickbeard.TRIM_ZERO then 'true' else 'false'# + }); + #end if + + }); +//--> +</script> + + #set $show_div = 'listing-default' + +<input type="hidden" id="sbRoot" value="$sbRoot" /> + +<table id="showListTable" class="sickbeardTable tablesorter seasonstyle" cellspacing="1" border="0" cellpadding="0"> + + <thead> + <tr> + <th>Airdate</th> + <th>Show</th> + <th class="nowrap">Next Ep</th> + <th>Next Ep Name</th> + <th>Network</th> + <th>Quality</th> + <th>Indexers</th> + <th>Search</th> + </tr> + </thead> + + <tbody style="text-shadow:none;"> + + #for $cur_result in $sql_results: + #set $cur_indexer = int($cur_result['indexer']) + #set $runtime = $cur_result['runtime'] + + #if int($cur_result['paused']) and not $sickbeard.EPISODE_VIEW_DISPLAY_PAUSED: + #continue + #end if + + #set $cur_ep_airdate = $cur_result['localtime'].date() + + #if $runtime: + #set $cur_ep_enddate = $cur_result['localtime'] + datetime.timedelta(minutes = $runtime) + #if $cur_ep_enddate < $today: + #set $show_div = 'listing-overdue' + #elif $cur_ep_airdate >= $next_week.date(): + #set $show_div = 'listing-toofar' + #elif $cur_ep_airdate >= $today.date() and $cur_ep_airdate < $next_week.date(): + #if $cur_ep_airdate == $today.date(): + #set $show_div = 'listing-current' + #else: + #set $show_div = 'listing-default' + #end if + #end if + #end if + + <!-- start $cur_result['show_name'] //--> + <tr class="$show_div"> + ## forced to use a div to wrap airdate, the column sort went crazy with a span + <td align="center" class="nowrap"> + <div class="${fuzzydate}">$sbdatetime.sbdatetime.sbfdatetime($cur_result['localtime']).decode($sickbeard.SYS_ENCODING)</div><span class="sort_data">$time.mktime($cur_result['localtime'].timetuple())</span> + </td> + + <td class="tvShow"><a href="$sbRoot/home/displayShow?show=${cur_result['showid']}" data-name="$cur_result['data_show_name']">$cur_result['show_name']</a> + #if int($cur_result['paused']): + <span class="pause">[paused]</span> + #end if + </td> + + <td class="nowrap" align="center"> + <%= 'S%02iE%02i' % (int(cur_result['season']), int(cur_result['episode'])) %> + </td> + + <td> + #if $cur_result['description']: + <img alt="" src="$sbRoot/images/info32.png" height="16" width="16" class="plotInfo" id="plot_info_<%= '%s_%s_%s' % (str(cur_result['showid']), str(cur_result['season']), str(cur_result['episode'])) %>" /> + #else: + <img alt="" src="$sbRoot/images/info32.png" width="16" height="16" class="plotInfoNone" /> + #end if + $cur_result['name'] + </td> + + <td align="center"> + <span data-network="$cur_result['data_network']">$cur_result['network']</span> + </td> + + <td align="center"> + #if int($cur_result['quality']) in $qualityPresets: + <span class="quality $qualityPresetStrings[int($cur_result['quality'])]">$qualityPresetStrings[int($cur_result['quality'])]</span> + #else: + <span class="quality Custom">Custom</span> + #end if + </td> + + <td align="center" style="vertical-align: middle;"> + #if $cur_result['imdb_id']: + <a href="<%= anon_url('http://www.imdb.com/title/', cur_result['imdb_id']) %>" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false" title="http://www.imdb.com/title/${cur_result['imdb_id']}"><img alt="[imdb]" height="16" width="16" src="$sbRoot/images/imdb.png" /> + #end if + <a href="<%= anon_url(sickbeard.indexerApi(cur_indexer).config['show_url'], cur_result['showid']) %>" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false" title="$sickbeard.indexerApi($cur_indexer).config['show_url']${cur_result['showid']}"><img alt="$sickbeard.indexerApi($cur_indexer).name" height="16" width="16" src="$sbRoot/images/$sickbeard.indexerApi($cur_indexer).config['icon']" /></a> + </td> + + <td align="center"> + <a href="$sbRoot/home/searchEpisode?show=${cur_result['showid']}&season=$cur_result['season']&episode=$cur_result['episode']" title="Manual Search" id="forceUpdate-${cur_result['showid']}" class="forceUpdate epSearch"><img alt="[search]" height="16" width="16" src="$sbRoot/images/search16.png" id="forceUpdateImage-${cur_result['showid']}" /></a> + </td> + </tr> + <!-- end $cur_result['show_name'] //--> + + #end for + + </tbody> + + <tfoot> + <tr> + <th rowspan="1" colspan="10" align="center"> </th> + </tr> + </tfoot> + +</table> +<!-- end list view //--> + + + +#else if $layout in ['banner', 'poster']: +<!-- start non list view //--> + +<script type="text/javascript" charset="utf-8"> +<!-- + \$(document).ready(function(){ + \$('#sbRoot').ajaxEpSearch({'size': 16, 'loadingImage': 'loading16' + themeSpinner + '.gif'}); + \$('.ep_summary').hide(); + \$('.ep_summaryTrigger').click(function() { + \$(this).next('.ep_summary').slideToggle('normal', function() { + \$(this).prev('.ep_summaryTrigger').attr('src', function(i, src) { + return \$(this).next('.ep_summary').is(':visible') ? src.replace('plus','minus') : src.replace('minus','plus') + }); + }); + }); + + #set $fuzzydate = 'airdate' + #if $sickbeard.FUZZY_DATING: + fuzzyMoment({ + dtInline : true, + dtGlue : ' at ', + containerClass : '.${fuzzydate}', + dateHasTime : true, + dateFormat : '${sickbeard.DATE_PRESET}', + timeFormat : '${sickbeard.TIME_PRESET}', + trimZero : #if $sickbeard.TRIM_ZERO then 'true' else 'false'# + }); + #end if + }); +//--> +</script> + + #set $cur_segment = None + #set $too_late_header = False + #set $missed_header = False + #set $today_header = False + #set $show_div = 'ep_listing listing-default' + + #if 'show' == $sort: + <br /><br /> + #end if + + #for $cur_result in $sql_results: + #set $cur_indexer = int($cur_result['indexer']) + + #if int($cur_result['paused']) and not $sickbeard.EPISODE_VIEW_DISPLAY_PAUSED: + #continue + #end if + + #set $runtime = $cur_result['runtime'] + + #if 'network' == $sort: + + #set $show_network = $cur_result['network'] if $cur_result['network'] else 'no network' + #if $cur_segment != $show_network: + <div class="episode-view-header"> + <br><h2 class="network">$show_network</h2> + #set $cur_segment = $cur_result['network'] + #end if + #set $cur_ep_airdate = $cur_result['localtime'].date() + + #if $runtime: + #set $cur_ep_enddate = $cur_result['localtime'] + datetime.timedelta(minutes = $runtime) + #if $cur_ep_enddate < $today: + #set $show_div = 'ep_listing listing-overdue' + #elif $cur_ep_airdate >= $next_week.date(): + #set $show_div = 'ep_listing listing-toofar' + #elif $cur_ep_enddate >= $today and $cur_ep_airdate < $next_week.date(): + #if $cur_ep_airdate == $today.date(): + #set $show_div = 'ep_listing listing-current' + #else: + #set $show_div = 'ep_listing listing-default' + #end if + #end if + #end if + + #elif 'time' == $sort: + + #set $cur_ep_airdate = $cur_result['localtime'].date() + + #if $cur_segment != $cur_ep_airdate: + #if $runtime: + #set $cur_ep_enddate = $cur_result['localtime'] + datetime.timedelta(minutes = $runtime) + #if $cur_ep_enddate < $today and $cur_ep_airdate != $today.date() and not $missed_header: + <br /><h2 class="day">Missed</h2> + #set $missed_header = True + #elif $cur_ep_airdate >= $next_week.date() and not $too_late_header: + <br /><h2 class="day">Later</h2> + #set $too_late_header = True + #elif $cur_ep_enddate >= $today and $cur_ep_airdate < $next_week.date(): + #if $cur_ep_airdate == $today.date(): + <br /><h2 class="day">$sbdatetime.sbdatetime.sbfdate($cur_ep_airdate, '%A').decode($sickbeard.SYS_ENCODING).capitalize() <span style="font-size: 14px; vertical-align: top;">[Today]</span></h2> + #set $today_header = True + #else: + <br /><h2 class="day">$sbdatetime.sbdatetime.sbfdate($cur_ep_airdate, '%A').decode($sickbeard.SYS_ENCODING).capitalize()</h2> + #end if + #end if + #end if + #set $cur_segment = $cur_ep_airdate + #end if + + #if $cur_ep_airdate == $today.date() and not $today_header: + <div class="episode-view-header"> + <br /><h2 class="day">$sbdatetime.sbdatetime.sbfdate($cur_ep_airdate, '%A').decode($sickbeard.SYS_ENCODING).capitalize() <span style="font-size: 14px; vertical-align: top;">[Today]</span></h2> + #set $today_header = True + #end if + + #if $runtime: + #set $cur_ep_enddate = $cur_result['localtime'] + datetime.timedelta(minutes = $runtime) + #if $cur_ep_enddate < $today: + #set $show_div = 'ep_listing listing-overdue' + #elif $cur_ep_airdate >= $next_week.date(): + #set $show_div = 'ep_listing listing-toofar' + #elif $cur_ep_enddate >= $today and $cur_ep_airdate < $next_week.date(): + #if $cur_ep_airdate == $today.date(): + #set $show_div = 'ep_listing listing-current' + #else: + #set $show_div = 'ep_listing listing-default' + #end if + #end if + #end if + + #elif 'show' == $sort: + #set $cur_ep_airdate = $cur_result['localtime'].date() + + #if $runtime: + #set $cur_ep_enddate = $cur_result['localtime'] + datetime.timedelta(minutes = $runtime) + #if $cur_ep_enddate < $today: + #set $show_div = 'ep_listing listing-overdue listingradius' + #elif $cur_ep_airdate >= $next_week.date(): + #set $show_div = 'ep_listing listing-toofar listingradius' + #elif $cur_ep_enddate >= $today and $cur_ep_airdate < $next_week.date(): + #if $cur_ep_airdate == $today.date(): + #set $show_div = 'ep_listing listing-current listingradius' + #else: + #set $show_div = 'ep_listing listing-default listingradius' + #end if + #end if + #end if + #end if + +<!-- start $cur_result['show_name'] //--> +<div class="$show_div" id="listing-${cur_result['showid']}"> + <div class="tvshowDiv"> + <table width="100%" border="0" cellpadding="0" cellspacing="0"> + <tr> + <th #if 'banner' == $layout then 'class="nobg"' else 'rowspan="2"'# valign="top"> + <a href="$sbRoot/home/displayShow?show=${cur_result['showid']}"><img alt="" class="#if 'banner' == $layout then 'bannerThumb' else 'posterThumb'#" src="$sbRoot/showPoster/?show=${cur_result['showid']}&which=#if 'poster' == $layout then 'poster_thumb' else $layout#" /></a> + </th> + + #if 'banner' == $layout: + </tr> + <tr> + #end if + + <td class="next_episode"> + <div class="clearfix"> + <span class="tvshowTitle"> + <a href="$sbRoot/home/displayShow?show=${cur_result['showid']}" data-name="$cur_result['data_show_name']">$cur_result['show_name'] + #if int($cur_result['paused']): + <span class="pause">[paused]</span> + #end if + </a></span> + + <span class="tvshowTitleIcons"> + #if $cur_result['imdb_id']: + <a href="<%= anon_url('http://www.imdb.com/title/', cur_result['imdb_id']) %>" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false" title="http://www.imdb.com/title/${cur_result['imdb_id']}"><img alt="[imdb]" height="16" width="16" src="$sbRoot/images/imdb.png" /> + #end if + <a href="<%= anon_url(sickbeard.indexerApi(cur_indexer).config['show_url'], cur_result['showid']) %>" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false" title="$sickbeard.indexerApi($cur_indexer).config['show_url']${cur_result['showid']}"><img alt="$sickbeard.indexerApi($cur_indexer).name" height="16" width="16" src="$sbRoot/images/$sickbeard.indexerApi($cur_indexer).config['icon']" /></a> + <span><a href="$sbRoot/home/searchEpisode?show=${cur_result['showid']}&season=$cur_result['season']&episode=$cur_result['episode']" title="Manual Search" id="forceUpdate-${cur_result['showid']}" class="epSearch forceUpdate"><img alt="[search]" height="16" width="16" src="$sbRoot/images/search16.png" id="forceUpdateImage-${cur_result['showid']}" /></a></span> + </span> + </div> + + <span class="title">Next Episode:</span> <span><%= 'S%02iE%02i' % (int(cur_result['season']), int(cur_result['episode'])) %> - $cur_result['name']</span> + + <div class="clearfix"> + + <span class="title">Airdate: </span><span class="${fuzzydate}">$sbdatetime.sbdatetime.sbfdatetime($cur_result['localtime']).decode($sickbeard.SYS_ENCODING)</span><%= ('', '<span> on %s</span>' % str(cur_result['network']))[None is not cur_result['network']] %> + </div> + + <div class="clearfix"> + <span class="title">Quality:</span> + #if int($cur_result['quality']) in $qualityPresets: + <span class="quality $qualityPresetStrings[int($cur_result['quality'])]">$qualityPresetStrings[int($cur_result['quality'])]</span> + #else: + <span class="quality Custom">Custom</span> + #end if + </div> + </td> + </tr> + <tr> + <td style="vertical-align: top;"> + <div> + #if $cur_result['description']: + <span class="title" style="vertical-align:middle;">Plot:</span> + <img class="ep_summaryTrigger" src="$sbRoot/images/plus.png" height="16" width="16" alt="" title="Toggle Summary" /><div class="ep_summary">$cur_result['description']</div> + #else: + <span class="title ep_summaryTriggerNone" style="vertical-align:middle;">Plot:</span> + <img class="ep_summaryTriggerNone" src="$sbRoot/images/plus.png" height="16" width="16" alt="" /> + #end if + </div> + </td> + </tr> + </table> + </div> +</div> +<!-- end $cur_result['show_name'] //--> + #end for +<!-- end non list view //--> +#end if + + + +#if 'daybyday' == $layout: + + #set $today = datetime.date.today() + #set $dates = [$today + datetime.timedelta(days = $i) for $i in range(7)] + #set $tbl_day = 0 + +<input type="hidden" id="sbRoot" value="$sbRoot" /> + +<br> +<br> +<div class="daybydayWrapper"> <!-- style="width:1600px" --> + #for $day in $dates + #set $tbl_day += 1 + + #set $col_class = '' + #if 1 == $tbl_day + #set $col_class = 'today' + #end if + #set $col_class = '%s %s' % ($col_class, ('even', 'odd')[1 == tbl_day % 2]) + + <div class="day-of-week $col_class"> + <div class="day-number"> + <div class="number">$sbdatetime.sbdatetime.sbfdate($day, ' %d').decode($sickbeard.SYS_ENCODING).replace(' 0', ' ')</div> + <div class="day"> + <span class="visible-lg">$sbdatetime.sbdatetime.sbfdate($day, '%A').decode($sickbeard.SYS_ENCODING).capitalize()</span> + <span class="hidden-lg">$sbdatetime.sbdatetime.sbfdate($day, '%a').decode($sickbeard.SYS_ENCODING).capitalize()</span> + </div> + <div class="month"> + <span class="visible-lg">$sbdatetime.sbdatetime.sbfdate($day, '%B').decode($sickbeard.SYS_ENCODING).capitalize()</span> + <span class="hidden-lg">$sbdatetime.sbdatetime.sbfdate($day, '%b').decode($sickbeard.SYS_ENCODING).capitalize()</span> + </div> + </div> + <div id="$sbdatetime.sbdatetime.sbfdate($day, 'day%w')"> + + #set $day_has_show = False + #for $cur_result in $sql_results: + #if int($cur_result['paused']) and not $sickbeard.EPISODE_VIEW_DISPLAY_PAUSED: + #continue + #end if + + #set $cur_indexer = int($cur_result['indexer']) + #set $runtime = $cur_result['runtime'] + #set $airday = $cur_result['localtime'].date() + + #if $airday == $day: + #set $day_has_show = True + #set $airtime = $sbdatetime.sbdatetime.sbftime($cur_result['localtime'], markup=True).decode($sickbeard.SYS_ENCODING) + #set $img_tag = '<img' + #set $plot_class = 'class="img-responsive' + #set $title_text = '' + #if $cur_result['description']: + #set $img_tag += ' id="plot_info_%s_%s_%s"' % (str($cur_result['showid']), str($cur_result['season']), str($cur_result['episode'])) + #set $plot_class += ' plot-daybyday' + #else + #set $title_text = $cur_result['show_name'] + #end if + + <div id="show-$cur_result['showid']" class="daybyday-show" data-name="$cur_result['data_show_name']" data-season="$cur_result['season']" data-episode="$cur_result['episode']" data-network="$cur_result['data_network']" data-time="$time.mktime($cur_result['localtime'].timetuple())"> + <div class="poster"> + <a title="${title_text}" href="$sbRoot/home/displayShow?show=${cur_result['showid']}"> + ${img_tag} ${plot_class}" alt="" src="$sbRoot/showPoster/?show=${cur_result['showid']}&which=poster_thumb" /></a> + </div> + <div class="text"> + <div class="airtime"> + <span class="time">${airtime}</span> <span class="network pull-right grey-text">$cur_result['network']</span> + </div> + <div class="episode" title="$cur_result['name']"> + <span class="season"><%= '%i' % int(cur_result['season']) %></span>x<span class="number"><%= '%02i' % int(cur_result['episode']) %></span> + <span class="name">$cur_result['name']</span> + #if int($cur_result['paused']): + <span class="pause">[paused]</span> + #end if + </div> + </div> + </div><!-- end show-$cur_result['showid'] //--> + + #end if + + #end for + #if not $day_has_show: + <div class="daybyday-show"> + <span class="episode-blank">No shows for this day</span> + </div> + #end if + </div> + </div> + #end for +</div> + +<!-- end calender view //--> +#end if + +<div class="clearfix"></div> + +<script type="text/javascript" charset="utf-8"> +<!-- +window.setInterval('location.reload(true)', 30*60000); // Refresh every xx minutes +//--> +</script> + +#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_bottom.tmpl') diff --git a/gui/slick/interfaces/default/home_trendingShows.tmpl b/gui/slick/interfaces/default/home_trendingShows.tmpl index 3197db5b..bef8709b 100644 --- a/gui/slick/interfaces/default/home_trendingShows.tmpl +++ b/gui/slick/interfaces/default/home_trendingShows.tmpl @@ -11,7 +11,7 @@ #set global $sbPath='..' -#set global $topmenu='comingEpisodes' +#set global $topmenu='episodeView' #import os.path #include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_top.tmpl') diff --git a/gui/slick/interfaces/default/inc_top.tmpl b/gui/slick/interfaces/default/inc_top.tmpl index e854d60f..d29591be 100644 --- a/gui/slick/interfaces/default/inc_top.tmpl +++ b/gui/slick/interfaces/default/inc_top.tmpl @@ -150,8 +150,8 @@ </ul> </li> - <li id="NAVcomingEpisodes"> - <a href="$sbRoot/comingEpisodes/" tabindex="$tab#set $tab += 1#">Coming Episodes</a> + <li id="NAVepisodeView"> + <a href="$sbRoot/episodeView/" tabindex="$tab#set $tab += 1#">Episodes</a> </li> <li id="NAVhistory"> @@ -262,6 +262,6 @@ #except (NameError, NotFound): #pass #end try -#set $page_class = ('', ' class="%s"' % '_'.join($items).lower().replace(' ', '-'))[0 < len($items)] +#set $page_class = ('', ' class="%s"' % '_'.join($items).lower().replace(' ', '-').replace('_', '-'))[0 < len($items)] <div id="contentWrapper"> <div id="content"$page_class> diff --git a/gui/slick/js/plotTooltip.js b/gui/slick/js/plotTooltip.js index b15009d3..b3d911e3 100644 --- a/gui/slick/js/plotTooltip.js +++ b/gui/slick/js/plotTooltip.js @@ -1,5 +1,5 @@ $(function () { - $('.plotInfo').each(function () { + $('.plotInfo, .plot-daybyday').each(function () { var match = $(this).attr('id').match(/^plot_info_(\d+)_(\d+)_(\d+)$/); $(this).qtip({ content: { diff --git a/sickbeard/__init__.py b/sickbeard/__init__.py index 42204efa..1ac49e1e 100755 --- a/sickbeard/__init__.py +++ b/sickbeard/__init__.py @@ -58,7 +58,7 @@ CFG = None CONFIG_FILE = None # This is the version of the config we EXPECT to find -CONFIG_VERSION = 6 +CONFIG_VERSION = 7 # Default encryption version (0 for None) ENCRYPTION_VERSION = 0 @@ -419,10 +419,10 @@ GUI_NAME = None HOME_LAYOUT = None HISTORY_LAYOUT = None DISPLAY_SHOW_SPECIALS = False -COMING_EPS_LAYOUT = None -COMING_EPS_DISPLAY_PAUSED = False -COMING_EPS_SORT = None -COMING_EPS_MISSED_RANGE = None +EPISODE_VIEW_LAYOUT = None +EPISODE_VIEW_SORT = None +EPISODE_VIEW_DISPLAY_PAUSED = False +EPISODE_VIEW_MISSED_RANGE = None FUZZY_DATING = False TRIM_ZERO = False DATE_PRESET = None @@ -499,7 +499,7 @@ def initialize(consoleLogging=True): USE_EMAIL, EMAIL_HOST, EMAIL_PORT, EMAIL_TLS, EMAIL_USER, EMAIL_PASSWORD, EMAIL_FROM, EMAIL_NOTIFY_ONSNATCH, EMAIL_NOTIFY_ONDOWNLOAD, EMAIL_NOTIFY_ONSUBTITLEDOWNLOAD, EMAIL_LIST, \ USE_LISTVIEW, METADATA_XBMC, METADATA_XBMC_12PLUS, METADATA_MEDIABROWSER, METADATA_PS3, metadata_provider_dict, \ NEWZBIN, NEWZBIN_USERNAME, NEWZBIN_PASSWORD, GIT_PATH, MOVE_ASSOCIATED_FILES, POSTPONE_IF_SYNC_FILES, recentSearchScheduler, NFO_RENAME, \ - GUI_NAME, HOME_LAYOUT, HISTORY_LAYOUT, DISPLAY_SHOW_SPECIALS, COMING_EPS_LAYOUT, COMING_EPS_SORT, COMING_EPS_DISPLAY_PAUSED, COMING_EPS_MISSED_RANGE, FUZZY_DATING, TRIM_ZERO, DATE_PRESET, TIME_PRESET, TIME_PRESET_W_SECONDS, THEME_NAME, \ + GUI_NAME, HOME_LAYOUT, HISTORY_LAYOUT, DISPLAY_SHOW_SPECIALS, EPISODE_VIEW_LAYOUT, EPISODE_VIEW_SORT, EPISODE_VIEW_DISPLAY_PAUSED, EPISODE_VIEW_MISSED_RANGE, FUZZY_DATING, TRIM_ZERO, DATE_PRESET, TIME_PRESET, TIME_PRESET_W_SECONDS, THEME_NAME, \ POSTER_SORTBY, POSTER_SORTDIR, \ METADATA_WDTV, METADATA_TIVO, METADATA_MEDE8ER, IGNORE_WORDS, REQUIRE_WORDS, CALENDAR_UNPROTECTED, CREATE_MISSING_SHOW_DIRS, \ ADD_SHOWS_WO_DIR, USE_SUBTITLES, SUBTITLES_LANGUAGES, SUBTITLES_DIR, SUBTITLES_SERVICES_LIST, SUBTITLES_SERVICES_ENABLED, SUBTITLES_HISTORY, SUBTITLES_FINDER_FREQUENCY, subtitlesFinderScheduler, \ @@ -944,10 +944,10 @@ def initialize(consoleLogging=True): 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)) - COMING_EPS_LAYOUT = check_setting_str(CFG, 'GUI', 'coming_eps_layout', 'banner') - COMING_EPS_DISPLAY_PAUSED = bool(check_setting_int(CFG, 'GUI', 'coming_eps_display_paused', 0)) - COMING_EPS_SORT = check_setting_str(CFG, 'GUI', 'coming_eps_sort', 'date') - COMING_EPS_MISSED_RANGE = check_setting_int(CFG, 'GUI', 'coming_eps_missed_range', 7) + 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) FUZZY_DATING = bool(check_setting_int(CFG, 'GUI', 'fuzzy_dating', 0)) TRIM_ZERO = bool(check_setting_int(CFG, 'GUI', 'trim_zero', 0)) DATE_PRESET = check_setting_str(CFG, 'GUI', 'date_preset', '%x') @@ -1763,10 +1763,10 @@ def save_config(): new_config['GUI']['home_layout'] = HOME_LAYOUT new_config['GUI']['history_layout'] = HISTORY_LAYOUT new_config['GUI']['display_show_specials'] = int(DISPLAY_SHOW_SPECIALS) - new_config['GUI']['coming_eps_layout'] = COMING_EPS_LAYOUT - new_config['GUI']['coming_eps_display_paused'] = int(COMING_EPS_DISPLAY_PAUSED) - new_config['GUI']['coming_eps_sort'] = COMING_EPS_SORT - new_config['GUI']['coming_eps_missed_range'] = int(COMING_EPS_MISSED_RANGE) + new_config['GUI']['episode_view_layout'] = EPISODE_VIEW_LAYOUT + new_config['GUI']['episode_view_display_paused'] = int(EPISODE_VIEW_DISPLAY_PAUSED) + new_config['GUI']['episode_view_sort'] = EPISODE_VIEW_SORT + new_config['GUI']['episode_view_missed_range'] = int(EPISODE_VIEW_MISSED_RANGE) new_config['GUI']['fuzzy_dating'] = int(FUZZY_DATING) new_config['GUI']['trim_zero'] = int(TRIM_ZERO) new_config['GUI']['date_preset'] = DATE_PRESET diff --git a/sickbeard/config.py b/sickbeard/config.py index bcbfc025..322861d4 100644 --- a/sickbeard/config.py +++ b/sickbeard/config.py @@ -448,8 +448,9 @@ class ConfigMigrator(): 3: 'Rename omgwtfnzb variables', 4: 'Add newznab catIDs', 5: 'Metadata update', - 6: 'Rename daily search to recent search' - } + 6: 'Rename daily search to recent search', + 7: 'Rename coming episodes to episode view' + } def migrate_config(self): """ @@ -729,4 +730,13 @@ class ConfigMigrator(): for curProvider in providers.sortedProviderList(): if hasattr(curProvider, 'enable_recentsearch'): curProvider.enable_recentsearch = bool(check_setting_int(self.config_obj, curProvider.getID().upper(), - curProvider.getID() + '_enable_dailysearch', 1)) \ No newline at end of file + curProvider.getID() + '_enable_dailysearch', 1)) + + def _migrate_v7(self): + + sickbeard.EPISODE_VIEW_LAYOUT = check_setting_str(self.config_obj, 'GUI', 'coming_eps_layout', 'banner') + sickbeard.EPISODE_VIEW_SORT = check_setting_str(self.config_obj, 'GUI', 'coming_eps_sort', 'time') + if 'date' == sickbeard.EPISODE_VIEW_SORT: + sickbeard.EPISODE_VIEW_SORT = 'time' + sickbeard.EPISODE_VIEW_DISPLAY_PAUSED = bool(check_setting_int(self.config_obj, 'GUI', 'coming_eps_display_paused', 0)) + sickbeard.EPISODE_VIEW_MISSED_RANGE = check_setting_int(self.config_obj, 'GUI', 'coming_eps_missed_range', 7) diff --git a/sickbeard/webapi.py b/sickbeard/webapi.py index 0051d23c..3999fbc2 100644 --- a/sickbeard/webapi.py +++ b/sickbeard/webapi.py @@ -711,7 +711,7 @@ class CMD_ComingEpisodes(ApiCall): self.sort, args = self.check_params(args, kwargs, "sort", "date", False, "string", ["date", "show", "network"]) self.type, args = self.check_params(args, kwargs, "type", "today|missed|soon|later", False, "list", ["missed", "later", "today", "soon"]) - self.paused, args = self.check_params(args, kwargs, "paused", sickbeard.COMING_EPS_DISPLAY_PAUSED, False, "int", + self.paused, args = self.check_params(args, kwargs, "paused", sickbeard.EPISODE_VIEW_DISPLAY_PAUSED, False, "int", [0, 1]) # super, missing, help ApiCall.__init__(self, handler, args, kwargs) @@ -725,7 +725,7 @@ class CMD_ComingEpisodes(ApiCall): tomorrow = (datetime.date.today() + datetime.timedelta(days=1)).toordinal() next_week_dt = (datetime.date.today() + datetime.timedelta(days=7)) next_week = (next_week_dt + datetime.timedelta(days=1)).toordinal() - recently = (yesterday_dt - datetime.timedelta(days=sickbeard.COMING_EPS_MISSED_RANGE)).toordinal() + recently = (yesterday_dt - datetime.timedelta(days=sickbeard.EPISODE_VIEW_MISSED_RANGE)).toordinal() done_show_list = [] qualList = Quality.DOWNLOADED + Quality.SNATCHED + [ARCHIVED, IGNORED] @@ -758,31 +758,27 @@ class CMD_ComingEpisodes(ApiCall): # multi dimension sort sorts = { 'date': (lambda a, b: cmp( - (a['parsed_datetime'], - (a['show_name'], remove_article(a['show_name']))[not sickbeard.SORT_ARTICLE], - a['season'], a['episode']), - (b['parsed_datetime'], - (b['show_name'], remove_article(b['show_name']))[not sickbeard.SORT_ARTICLE], - b['season'], b['episode']))), - 'show': (lambda a, b: cmp( - ((a['show_name'], remove_article(a['show_name']))[not sickbeard.SORT_ARTICLE], - a['parsed_datetime'], a['season'], a['episode']), - ((b['show_name'], remove_article(b['show_name']))[not sickbeard.SORT_ARTICLE], - b['parsed_datetime'], b['season'], b['episode']))), + (a['parsed_datetime'], a['data_show_name'], a['season'], a['episode']), + (b['parsed_datetime'], b['data_show_name'], b['season'], b['episode']))), 'network': (lambda a, b: cmp( - (a['network'], a['parsed_datetime'], - (a['show_name'], remove_article(a['show_name']))[not sickbeard.SORT_ARTICLE], - a['season'], a['episode']), - (b['network'], b['parsed_datetime'], - (b['show_name'], remove_article(b['show_name']))[not sickbeard.SORT_ARTICLE], - b['season'], b['episode']))) + (a['data_network'], a['parsed_datetime'], a['data_show_name'], a['season'], a['episode']), + (b['data_network'], b['parsed_datetime'], b['data_show_name'], b['season'], b['episode']))), + 'show': (lambda a, b: cmp( + (a['data_show_name'], a['parsed_datetime'], a['season'], a['episode']), + (b['data_show_name'], b['parsed_datetime'], b['season'], b['episode']))) } + def value_maybe_article(value=''): + return (remove_article(value.lower()), value.lower())[sickbeard.SORT_ARTICLE] + # add parsed_datetime to the dict for index, item in enumerate(sql_results): sql_results[index]['parsed_datetime'] = 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[self.sort]) + finalEpResults = {} # add all requested types or all @@ -1507,7 +1503,7 @@ class CMD_SickBeardGetDefaults(ApiCall): data = {"status": statusStrings[sickbeard.STATUS_DEFAULT].lower(), "flatten_folders": int(sickbeard.FLATTEN_FOLDERS_DEFAULT), "initial": anyQualities, - "archive": bestQualities, "future_show_paused": int(sickbeard.COMING_EPS_DISPLAY_PAUSED)} + "archive": bestQualities, "future_show_paused": int(sickbeard.EPISODE_VIEW_DISPLAY_PAUSED)} return _responds(RESULT_SUCCESS, data) @@ -1756,7 +1752,7 @@ class CMD_SickBeardSetDefaults(ApiCall): sickbeard.FLATTEN_FOLDERS_DEFAULT = int(self.flatten_folders) if self.future_show_paused != None: - sickbeard.COMING_EPS_DISPLAY_PAUSED = int(self.future_show_paused) + sickbeard.EPISODE_VIEW_DISPLAY_PAUSED = int(self.future_show_paused) return _responds(RESULT_SUCCESS, msg="Saved defaults") diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py index 2519e222..0751421b 100644 --- a/sickbeard/webserve.py +++ b/sickbeard/webserve.py @@ -67,7 +67,7 @@ from lib.dateutil import tz from lib.unrar2 import RarFile from lib import subliminal -from trakt import TraktCall +from lib.trakt import TraktCall try: import json @@ -300,7 +300,7 @@ class MainHandler(RequestHandler): def setPosterSortBy(self, sort): - if sort not in ('name', 'date', 'network', 'progress'): + if sort not in ('name', 'time', 'network', 'progress'): sort = 'name' sickbeard.POSTER_SORTBY = sort @@ -326,36 +326,40 @@ class MainHandler(RequestHandler): redirect("/home/displayShow?show=" + show) - def setComingEpsLayout(self, layout): - if layout not in ('poster', 'banner', 'list', 'calendar'): + def setEpisodeViewLayout(self, layout): + if layout not in ('poster', 'banner', 'list', 'daybyday'): layout = 'banner' - if layout == 'calendar': - sickbeard.COMING_EPS_SORT = 'date' + if 'daybyday' == layout: + sickbeard.EPISODE_VIEW_SORT = 'time' - sickbeard.COMING_EPS_LAYOUT = layout + sickbeard.EPISODE_VIEW_LAYOUT = layout - redirect("/comingEpisodes/") + sickbeard.save_config() - def toggleComingEpsDisplayPaused(self, *args, **kwargs): + redirect("/episodeView/") - sickbeard.COMING_EPS_DISPLAY_PAUSED = not sickbeard.COMING_EPS_DISPLAY_PAUSED + def toggleEpisodeViewDisplayPaused(self, *args, **kwargs): - redirect("/comingEpisodes/") + sickbeard.EPISODE_VIEW_DISPLAY_PAUSED = not sickbeard.EPISODE_VIEW_DISPLAY_PAUSED - def setComingEpsSort(self, sort): - if sort not in ('date', 'network', 'show'): - sort = 'date' + sickbeard.save_config() - if sickbeard.COMING_EPS_LAYOUT == 'calendar': - sort = 'date' + redirect("/episodeView/") - sickbeard.COMING_EPS_SORT = sort + def setEpisodeViewSort(self, sort, redir=1): + if sort not in ('time', 'network', 'show'): + sort = 'time' - redirect("/comingEpisodes/") + sickbeard.EPISODE_VIEW_SORT = sort - def comingEpisodes(self, layout="None"): - """ display the coming episodes """ + sickbeard.save_config() + + if int(redir): + redirect("/episodeView/") + + def episodeView(self, layout="None"): + """ display the episodes """ today_dt = datetime.date.today() #today = today_dt.toordinal() yesterday_dt = today_dt - datetime.timedelta(days=1) @@ -363,8 +367,8 @@ class MainHandler(RequestHandler): tomorrow = (datetime.date.today() + datetime.timedelta(days=1)).toordinal() next_week_dt = (datetime.date.today() + datetime.timedelta(days=7)) next_week = (next_week_dt + datetime.timedelta(days=1)).toordinal() - if not (layout and layout in ('calendar')) and not (sickbeard.COMING_EPS_LAYOUT and sickbeard.COMING_EPS_LAYOUT in ('calendar')): - recently = (yesterday_dt - datetime.timedelta(days=sickbeard.COMING_EPS_MISSED_RANGE)).toordinal() + if not (layout and layout in 'daybyday') and not (sickbeard.EPISODE_VIEW_LAYOUT and sickbeard.EPISODE_VIEW_LAYOUT in 'daybyday'): + recently = (yesterday_dt - datetime.timedelta(days=sickbeard.EPISODE_VIEW_MISSED_RANGE)).toordinal() else: recently = yesterday @@ -379,7 +383,7 @@ class MainHandler(RequestHandler): for cur_result in sql_results: done_show_list.append(int(cur_result["showid"])) - if not (layout and layout in ('calendar')) and not (sickbeard.COMING_EPS_LAYOUT and sickbeard.COMING_EPS_LAYOUT in ('calendar')): + if not (layout and layout in 'daybyday') and not (sickbeard.EPISODE_VIEW_LAYOUT and sickbeard.EPISODE_VIEW_LAYOUT in 'daybyday'): more_sql_results = myDB.select( "SELECT *, tv_shows.status as show_status FROM tv_episodes outer_eps, tv_shows WHERE season != 0 AND showid NOT IN (" + ','.join( ['?'] * len( @@ -395,49 +399,44 @@ class MainHandler(RequestHandler): sql_results = list(set(sql_results)) - # multi dimension sort - sorts = { - 'date': (lambda a, b: cmp( - (a['localtime'], - (a['show_name'], remove_article(a['show_name']))[not sickbeard.SORT_ARTICLE], - a['season'], a['episode']), - (b['localtime'], - (b['show_name'], remove_article(b['show_name']))[not sickbeard.SORT_ARTICLE], - b['season'], b['episode']))), - 'show': (lambda a, b: cmp( - ((a['show_name'], remove_article(a['show_name']))[not sickbeard.SORT_ARTICLE], - a['localtime'], a['season'], a['episode']), - ((b['show_name'], remove_article(b['show_name']))[not sickbeard.SORT_ARTICLE], - b['localtime'], b['season'], b['episode']))), - 'network': (lambda a, b: cmp( - (a['network'], a['localtime'], - (a['show_name'], remove_article(a['show_name']))[not sickbeard.SORT_ARTICLE], - a['season'], a['episode']), - (b['network'], b['localtime'], - (b['show_name'], remove_article(b['show_name']))[not sickbeard.SORT_ARTICLE], - b['season'], b['episode']))) - } - # make a dict out of the sql results sql_results = [dict(row) for row in sql_results] + # multi dimension sort + sorts = { + 'network': (lambda a, b: cmp( + (a['data_network'], a['localtime'], a['data_show_name'], a['season'], a['episode']), + (b['data_network'], b['localtime'], b['data_show_name'], b['season'], b['episode']))), + 'show': (lambda a, b: cmp( + (a['data_show_name'], a['localtime'], a['season'], a['episode']), + (b['data_show_name'], b['localtime'], b['season'], b['episode']))), + 'time': (lambda a, b: cmp( + (a['localtime'], a['data_show_name'], a['season'], a['episode']), + (b['localtime'], b['data_show_name'], b['season'], b['episode']))) + } + + def value_maybe_article(value=''): + return (remove_article(value.lower()), value.lower())[sickbeard.SORT_ARTICLE] + # add localtime to the dict 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.COMING_EPS_SORT]) + sql_results.sort(sorts[sickbeard.EPISODE_VIEW_SORT]) - t = PageTemplate(headers=self.request.headers, file="comingEpisodes.tmpl") + 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 # Allow local overriding of layout parameter - if layout and layout in ('poster', 'banner', 'list','calendar'): + if layout and layout in ('banner', 'daybyday', 'list', 'poster'): t.layout = layout else: - t.layout = sickbeard.COMING_EPS_LAYOUT + t.layout = sickbeard.EPISODE_VIEW_LAYOUT return _munge(t) @@ -549,7 +548,7 @@ class PageTemplate(Template): self.sbPID = str(sickbeard.PID) self.menu = [ {'title': 'Home', 'key': 'home'}, - {'title': 'Coming Episodes', 'key': 'comingEpisodes'}, + {'title': 'Episodes', 'key': 'episodeView'}, {'title': 'History', 'key': 'history'}, {'title': 'Manage', 'key': 'manage'}, {'title': 'Config', 'key': 'config'}, From 3b4346b053021c10972b52a37367bd4786130812 Mon Sep 17 00:00:00 2001 From: Prinz23 <Prinz2311@gmail.com> Date: Fri, 9 Jan 2015 21:41:45 +0100 Subject: [PATCH 17/21] Fix for: 'NoneType' object is not iterable in trakt module --- sickbeard/notifiers/trakt.py | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/sickbeard/notifiers/trakt.py b/sickbeard/notifiers/trakt.py index 840d2567..d0905d29 100644 --- a/sickbeard/notifiers/trakt.py +++ b/sickbeard/notifiers/trakt.py @@ -83,23 +83,24 @@ class TraktNotifier: # Start by getting all episodes in the watchlist watchlist = TraktCall("user/watchlist/episodes.json/%API%/" + sickbeard.TRAKT_USERNAME, sickbeard.TRAKT_API, sickbeard.TRAKT_USERNAME, sickbeard.TRAKT_PASSWORD) - # Convert watchlist to only contain current show - for show in watchlist: - # Check if tvdb_id exists - if 'tvdb_id' in show: - if unicode(data['shows'][0]['tvdb_id']) == show['tvdb_id']: - data_show = { - 'title': show['title'], - 'tvdb_id': show['tvdb_id'], - 'episodes': [] - } - - # Add series and episode (number) to the arry - for episodes in show['episodes']: - ep = {'season': episodes['season'], 'episode': episodes['number']} - data_show['episodes'].append(ep) - if data_show is not None: - TraktCall("show/episode/unwatchlist/%API%", sickbeard.TRAKT_API, sickbeard.TRAKT_USERNAME, sickbeard.TRAKT_PASSWORD, data_show) + if watchlist is not None: + # Convert watchlist to only contain current show + for show in watchlist: + # Check if tvdb_id exists + if 'tvdb_id' in show: + if unicode(data['shows'][0]['tvdb_id']) == show['tvdb_id']: + data_show = { + 'title': show['title'], + 'tvdb_id': show['tvdb_id'], + 'episodes': [] + } + + # Add series and episode (number) to the arry + for episodes in show['episodes']: + ep = {'season': episodes['season'], 'episode': episodes['number']} + data_show['episodes'].append(ep) + if data_show is not None: + TraktCall("show/episode/unwatchlist/%API%", sickbeard.TRAKT_API, sickbeard.TRAKT_USERNAME, sickbeard.TRAKT_PASSWORD, data_show) def test_notify(self, api, username, password): """ From a36fe55d413bdda27d53a3023c578d260f1eba67 Mon Sep 17 00:00:00 2001 From: Adam <adam111316@users.noreply.github.com> Date: Sat, 10 Jan 2015 10:21:53 +0800 Subject: [PATCH 18/21] Add log message for when trakt does not return a watchlist --- CHANGES.md | 2 ++ sickbeard/notifiers/trakt.py | 3 +++ 2 files changed, 5 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 6adf19de..d3d1b7bb 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -77,6 +77,8 @@ * Fix restart issue * Fix to use new TorrentDay URLs * Fix typo in menu item Manage/Update XBMC +* Fix 'NoneType' object is not iterable in trakt module +* Add log message for when trakt does not return a watchlist ### 0.4.0 (2014-12-04 10:50:00 UTC) diff --git a/sickbeard/notifiers/trakt.py b/sickbeard/notifiers/trakt.py index d0905d29..c58fa11f 100644 --- a/sickbeard/notifiers/trakt.py +++ b/sickbeard/notifiers/trakt.py @@ -101,6 +101,9 @@ class TraktNotifier: data_show['episodes'].append(ep) if data_show is not None: TraktCall("show/episode/unwatchlist/%API%", sickbeard.TRAKT_API, sickbeard.TRAKT_USERNAME, sickbeard.TRAKT_PASSWORD, data_show) + else: + logger.log('Failed to get watchlist from trakt. Unable to remove episode from watchlist', + logger.ERROR) def test_notify(self, api, username, password): """ From a96afe1ceb2dcf8fefe066f5b46a24e48cc5adc7 Mon Sep 17 00:00:00 2001 From: Adam <adam111316@users.noreply.github.com> Date: Sun, 11 Jan 2015 11:28:43 +0800 Subject: [PATCH 19/21] Bump version --- CHANGES.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index d3d1b7bb..9f337cb2 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,4 +1,4 @@ -### 0.x.x (2015-01-xx xx:xx:xx UTC) +### 0.6.0 (2015-01-11 03:28:00 UTC) * Add network logos BBC Canada, Crackle, El Rey Network, SKY Atlantic, and Watch * Change Yahoo! screen network logo @@ -34,8 +34,6 @@ * Change Epsiodes page auto refresh from 10 to 30 mins * Add UI tweaks -[develop changelog] - ### 0.5.0 (2014-12-21 11:40:00 UTC) From b1234286ae19ba1a655c4e5176fd80f6daffc3ea Mon Sep 17 00:00:00 2001 From: Supremicus <Supremicus@users.noreply.github.com> Date: Mon, 12 Jan 2015 22:26:41 +1000 Subject: [PATCH 20/21] Fix progress bars disappearing off homepage --- CHANGES.md | 1 + gui/slick/interfaces/default/home.tmpl | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 9f337cb2..84d4a63b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -33,6 +33,7 @@ * Add text "[paused]" where appropriate to shows on layout Day by Day on Episodes page * Change Epsiodes page auto refresh from 10 to 30 mins * Add UI tweaks +* Fix progress bars disappearing on home page ### 0.5.0 (2014-12-21 11:40:00 UTC) diff --git a/gui/slick/interfaces/default/home.tmpl b/gui/slick/interfaces/default/home.tmpl index 41ec20cc..f1cf254b 100644 --- a/gui/slick/interfaces/default/home.tmpl +++ b/gui/slick/interfaces/default/home.tmpl @@ -366,13 +366,13 @@ $myShowList.sort(lambda x, y: cmp(x.name, y.name)) if (classvalue<20) { classtoadd = "progress-20" } - if (classvalue>20 && classvalue<60) { + if (classvalue>=20 && classvalue<60) { classtoadd = "progress-40" } - if (classvalue>40 && classvalue<80) { + if (classvalue>=40 && classvalue<80) { classtoadd = "progress-60" } - if (classvalue>80) { + if (classvalue>=80) { classtoadd = "progress-80" } \$("\#progressbar$curShow.indexerid > .ui-progressbar-value").addClass(classtoadd); @@ -596,13 +596,13 @@ $myShowList.sort(lambda x, y: cmp(x.name, y.name)) if (classvalue<20) { classtoadd = "progress-20" } - if (classvalue>20 && classvalue<60) { + if (classvalue>=20 && classvalue<60) { classtoadd = "progress-40" } - if (classvalue>40 && classvalue<80) { + if (classvalue>=40 && classvalue<80) { classtoadd = "progress-60" } - if (classvalue>80) { + if (classvalue>=80) { classtoadd = "progress-80" } \$("\#progressbar$curShow.indexerid > .ui-progressbar-value").addClass(classtoadd); From 2f6db9fa9cdbf526a32c65870c78bb0f154fa6ed Mon Sep 17 00:00:00 2001 From: Adam <adam111316@users.noreply.github.com> Date: Sun, 18 Jan 2015 13:06:26 +0800 Subject: [PATCH 21/21] Bump release date --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 84d4a63b..b14e5ffd 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,4 +1,4 @@ -### 0.6.0 (2015-01-11 03:28:00 UTC) +### 0.6.0 (2015-01-18 05:05:00 UTC) * Add network logos BBC Canada, Crackle, El Rey Network, SKY Atlantic, and Watch * Change Yahoo! screen network logo