From 4e1de9bb527213dca454334f22ac535218544914 Mon Sep 17 00:00:00 2001 From: meeb Date: Thu, 10 Dec 2020 17:06:15 +1100 Subject: [PATCH] tweak logo and favicon, add django filestorage for download location, rework youtube-dl logging --- .../images/favicon-sources/tubesync-016.png | Bin 0 -> 632 bytes .../images/favicon-sources/tubesync-024.png | Bin 0 -> 988 bytes .../images/favicon-sources/tubesync-032.png | Bin 0 -> 1437 bytes .../images/favicon-sources/tubesync-048.png | Bin 0 -> 1987 bytes .../images/favicon-sources/tubesync-064.png | Bin 0 -> 2325 bytes .../images/favicon-sources/tubesync-096.png | Bin 0 -> 3971 bytes .../images/favicon-sources/tubesync-128.png | Bin 0 -> 4554 bytes tubesync/common/static/images/favicon.ico | Bin 45806 -> 22158 bytes tubesync/common/static/images/tubesync.png | Bin 0 -> 21763 bytes .../common/templates/tubesync-coloured.svg | 83 ++++++++++++++++++ tubesync/sync/models.py | 43 +++++---- tubesync/sync/templates/sync/media-item.html | 12 ++- tubesync/sync/utils.py | 6 +- tubesync/sync/youtube.py | 28 +++++- tubesync/tubesync/local_settings.py.container | 3 +- tubesync/tubesync/settings.py | 11 +-- 16 files changed, 154 insertions(+), 32 deletions(-) create mode 100644 tubesync/common/static/images/favicon-sources/tubesync-016.png create mode 100644 tubesync/common/static/images/favicon-sources/tubesync-024.png create mode 100644 tubesync/common/static/images/favicon-sources/tubesync-032.png create mode 100644 tubesync/common/static/images/favicon-sources/tubesync-048.png create mode 100644 tubesync/common/static/images/favicon-sources/tubesync-064.png create mode 100644 tubesync/common/static/images/favicon-sources/tubesync-096.png create mode 100644 tubesync/common/static/images/favicon-sources/tubesync-128.png create mode 100644 tubesync/common/static/images/tubesync.png create mode 100644 tubesync/common/templates/tubesync-coloured.svg diff --git a/tubesync/common/static/images/favicon-sources/tubesync-016.png b/tubesync/common/static/images/favicon-sources/tubesync-016.png new file mode 100644 index 0000000000000000000000000000000000000000..3f95ce16f95b49f44f45a9ae6227cf0df00f5a47 GIT binary patch literal 632 zcmV-;0*C#HP)}* zSab>Bon=sbo`qT3!EYp2;u246ObDD*pAii>C|>>kda}U*@#qteeo=gpO@mWWfn{fy z@KRj$JGRXB+9b>n)%jTsQGm;FiDhSa9%S2!0cL|t6Q2yy=&Ch5wJ{T3ib1Uwls-R7 z=Z#B9wpp-WJp$lg^p~^foQX(5Q|6A-!(`5#VaJyRQX|7nCWpjhCF~*#+)XOz2bXX{ z{kCOy-@8W7+7jNrUI1Q%ornl~#pAJ!&>zmy-!SQR*#35&u7@}4{8%li0to+y+bC1K zJ<}4`UQxa}TYcnQtI!w SWM@bK0000{`jG1)QA!dhA(?@Fh)jZ{ zFQFfb45ZTVOR-9{Sdo;LFDMu&WI+pAv}94c%D&9(+mP8D@4Iqvy-L_c`bM zpXd2MFXyUri2KZH{M5mTtwiQ|@&!yIsslaZUOH(1)sj zpBIlpak*068AwFfkd_(o2@X)e8k1pAM_i{28pt*59}{6^GEEk^OB;2pry$|S$j%JL?YWuwiZYl<3pKkz}6=dCDzQE-6gZEHSO z=!gv=PrAnWNbr0|l;>d`b)Cf3Z4&;ZiO|70T@qoJi*bRLMsQoak%4bNrttDQ^fgz_ zX=E^*=?mX)q_g!k{fl_M7l#J6+McF^nPqoluU|xA{VL||dym3P&$TyTGHBqFsKC`I z&WPu@Ppbw-d;+0bI&p3m%%||;8m>6D7kleXO=~wR&6iOxw`t3e$pG-at5gjf4weRW zrYp|P!UYWM|B(K7UauRPuXMdMmxSkcwFpK-GhM4Rmm;|*9%0__juzSm(DVb-wH(ZZ z=D9TZ&_q2svX4F3oHxLt>YZT=z|4ODm)Q#CkM=S1_O2#<45UbXpx7If;j}n@6Hif@ zuE1x%IK=d8+wgz=)3P>>XR@JW^#i&(j)r{lhcF-NfYDSK5LD zobc70J`{RGKOSCoyO={h;pwEriI8|dejWh#=if|k-p0hEtBAioI%i~Fggvh6=(DXzNpVC#0^Fwz!0YH+ZX#3w z2RJ50%V{YQsd(sR&1W+A?r!p>`t&T*CUa1i+AvxWA!T^t-OY z{?K)e@{Lcah;#(@B5X;^tWHZz0e2|F_9$PUqyY8>n`5QP@Pl`p5ywyBIVYY37!%Lp z;LVf>V?jTG=eT$5aWNC2=7)5|_9)-ljO{M{iU=1FE<=$E-hA#7Hl`&MFxjxTs5F~x z56hHk^1S1vpH+%0Y2N&Yc&5TV-52V7t;ukwww=exT)!>{MVm7OkOMUo}w ze>1>n4EF^Qb4n3TM(87X_ka(Or_g*x}*di0JoWtuTxC}0tXl_!gXCj zQ)%NQV4>f$MBu18RwUUH`28kgQ`AUC2A*XZggb+%=Gp`?yd2e2=l3<8u3w$x$a%Nl zVnSYs8miwEfhdF^=#xNNgxMx6pRU4&AdH}VCfK=MbGX_&T;Y5&h`S;+85e!-XG(+Egm2leR znqi4Vm|;R%5bic9HiQk#mLiEW>e%H;n4K;uy>wp>iPMv%W=^5`qt|JA{z=TJmTp9b zAUqS+vo@?F4cz7TKacXQ7IDp9{~*8|6AemE>+hXU^XG5Vu=D|>sS!*u{hCCWA4EhV zL?TT0rP%@e>WW@B2c0XP2AC{n(3);Cjbxr$&gGwOCVl&jHN(;%!qpz*xE66uE5(Nq z7>rzEX92>oS8~~gwKT3;(mgM{3IeoI6kyX)V#j}HaYAs_sP0~Zk^prUVp!*6lG97a zRp-#Z{~^EYdoHehrTbg~5!n<2#(2x42L6&OrsB9++y12Q_m|SkmbaT!E}AZ`lG%lPqUF zTU60PTx#3yY#aIQU(t5Ya@yBzgnXe-Pqm?ZYztnRi_HokoM-~3NWd>@IjD~3YzJ@H z0s-)$i+MOmgLTBa_mY}9h2+Rd+F#m4{N29(C#Nb0oMpH7z?EXS$%~$x9z9F9*_dTX z)+<8UW=Oy%sZ6S&~P#=lq5ItK&3#TIzY$9@ckC&Id_f!4ICV^xx4 ze~r1{0^8ic38*S3)Un>?dDhPw%?OKv6xW;TK|K7@B^+>;7KA*|fzsj2vU674;}T|> zuutH;Ds2=K?!^kXHzPb4q*xxNyZ4R-L5f>V#9_4@QdjyurH-5`G4Pp-s|ctnS>Pgy zdWE~->-=L|C}n%6+ZXi!Ub>hxi7;J4rgvF9u9m~jagORnkpMef%=Cg52|FnMrlD{LVyH)qh00000NkvXXu0mjf?|Yy6 literal 0 HcmV?d00001 diff --git a/tubesync/common/static/images/favicon-sources/tubesync-048.png b/tubesync/common/static/images/favicon-sources/tubesync-048.png new file mode 100644 index 0000000000000000000000000000000000000000..6a8217a61866a3b3926631d94ddd50d2212b247e GIT binary patch literal 1987 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 V(p^z7kgNaz002ovPDHLkV1kb-r2+r| literal 0 HcmV?d00001 diff --git a/tubesync/common/static/images/favicon-sources/tubesync-064.png b/tubesync/common/static/images/favicon-sources/tubesync-064.png new file mode 100644 index 0000000000000000000000000000000000000000..61aa895566c7ca727c7a398b36e310ccfd0ac203 GIT binary patch literal 2325 zcmV+w3F`KVP)Zg!XU%;b-}ckkUjzkBYv=XcIo@}C<%A@F}JS}{K4BzN$4VdEI*7!VH5Lg11R z7=eHt`x0Id95<>#3Hjdu;3daGCpYmjx5pf70~mq;x!Nt@jBv2kj^G7ua00+Qa zn%!4fWd+ef7;dKwHxq^%2rWJUk6B@C<7U?5=MjeaRKpUg;})9VPXAj7?BtOsYB8BY zDCQA{R;r!Id(c>Si=l-Fr%O*+shr?WsPJt_71|( zPBl!Y3^x&q$&zE1H2_0GV3rv`c#LtagkiJp!Hs#EW+s^$8NzUmbFTwIJJrxeHMCPL zI{=1+K(iS@rhyYc@T~5^3_AX?)q_?L-Q3P=jR_#=si*#Y#_6%Nk; z@DHOJ3yQSssj@6b(0{La&_r20>Qn;os$(fbS_43@QG*6TOA@{Uz>jh`2H#_qSd;>s z6aY&IJdh#CIc!wJQzFF^X;w?FWa$cz+2M?5z7C~V9ss_qxr;HrF3~FufPU`a zPYTmtL3J!-de&x7KQ;kca}($U|F{6~C060e243VAPI4zR0N=Gol>x-hbWheFR&mcl z_z%2@YhQj2{zF};-SIn+y4r$+(Cjkc`c8@!B+Wj}9qd(5+GlkagjHj>=E=vC9_iDj zqP}Mbyc^a66@?3rzs)MualYi)e&OI$f)ykIu+@o37n(~Lrn?|9#HR+!yJiI%PQ3YtKGf@ z^`~D4ZK%t7&aZS2sujNHlL}{eoI6nf4k@m_1yo0=glHQ4hyRM&uHOPxm3ghTh{*vs zDC{Tz$GDvFEh!PxOY#pb&1m@N9(dQU254^1c(Gz5PjDUuU_i)^KqF-+7xAw9A{x%T z0ll@wJ!w+hVy8vy2%ME97RrV2r1^(GKM8+tx9e!KUZT%gA))|W6zKr?NqGVQ0MzG2 z{n1^n=F~~_xrEpe2uduV8s!TB0FcTGS1i*f(I<4}8kF4uI?7*oU?l6YGH+&I0YLVW zm$~wnm#+iDqgjuaZL${ogBL&`<>d&7FrC#q%X3oJULy&iM>J_}o{=O?d!# zN&&!q)JO(EmHIj)91O-{gzwv797!;z4T>TP%*-c5TR-24pA-+U*meQy=Tp*~{CYn&?* z^h|1z>E{mGB@IXfP=-a@br0^80Y@pSA72k+(H$7=>PBem^RC0!e58llxZ4U!-|aW5 zF)0?`r1c2hZw8g+F_}yw6uV;WCgmh8kpRw1wrxJq@PhGS@cV56R_Um5_7lqr1y6twwyMNP5j5u_04b}VeqP~N{OCDku&lM_N64HUn4LlSZJH-dc_{!p9SfUsFzFxI z;gXsCIl=L9GXPce@dauqTltazIKdsP%CQ5y)3Hhdz;141ra7!szKKvgp{qN};s6ZA z8liKQK?n>LIg7O33T5nOs{+uiXD++P0cbOa^FGPnutP;ryocLpi3BqKG=~D{F=}9p zQQx2da87XiRI9>6)Ieh%8K8Z9eDeqI362hP1b16O=u7ta102J z-dN+*8{9@ViK#uh54RS$rr7D2c*-%A#3uF3ck8|}cYaI&R98*E;OG+$4s!=@3L7U= zBEcDiVW;8COW{-8!7grN54V)b44JH?1~%#LT4-I>zdeLt8ey0Qh7Oi&Eq%hl3C@)a zF;#wShjEZQ&|-;~VF+9lLYlqJM*g6Ca_VOwrTXdY5_1?w3&10mQyrVMDzF@jxh3m> z=*v_2`9#A;y)rGfziI#o=dt4tYn5?6pRbez0PZqiT1qwCM~!$ItB_JM3%CXZK?pdp vFX010Eg_f)iphlHcFHh^FiaiiHl66P)25)^BdCZFR2+Px@tL&@4o)(fk(p(DpiYdV#2Fzg z@fDWA7-bE~%IHXNKtVxg`2Z$F@G&Ba8lQ+U69oh#Z#DAn>guk0&)M^#OVZHQb#J}8 zyBhXd^?~l@oVxpe_Vet$uiA3>sloy3GIG1)mueCrg^&VPTf-``tP#Tov3!QGO@thnB7x#EC&q0~6-ucC0OU&>#j@N6{80=aTFYuNY$jYdP3F^rkVXzjK)&>ZNi*A| z*&vqP2!0W3)uSrv^mhpWEh22j@`y?EUnX7Bwd<5VAORhb72$as@U%_yf(0Y%iOS=Dc>&lgmPtX1#WpDWgH!>%4oJXX_58yo%>$-|ZJp$q zD4Yq3S{7H zlV+(6=#65q)|{jqPSg%3DwjTG_Nqz-fQYb605{2)A+| zn$xwz8QSFx?RKg0P8c zVXu>w!{c5xHA)pG0Zk%Y?k8E32lHLv7jB$yYp?8{MIlt96r;7r0_&G`pWeW)+&DEE z9^`H5j0mIs#=Mw+1ezsY4VOEyZpr+w=tifi?0d}dsySLad#U3*PkvKm=4;?uC&sI> z8iuslw7b%9-RjwtgETPBjdSWgHZSsSl5sWj@pkTW;QOaSCo5-n}LZjU4gC>HACx5n=2n{~EGbNPb8`>>NUUh_WnC>NV-qM8v z@UThqr-(*(fmdD8%>Ro1R(q7f5?rWV`h^(voWI>DmIpHVkFZ7l(~Wad4`4pP5bZFe z1m4gz)57|Y!<%!LJAxEDBINV0c4A!8%_7@kX?zJ{g5AJR{8V88ylw+th>)B*0?lNn zSMg6A^H7O6DiMd6*X00w+liGVRs4zsykz|R05Bp<3c|A@F7Q|^QFJLt?A+6-T{x3| zE0@r3MY?S6@FDd1^(4IE zL-zd48$N`ZJH}JHa3=9<#&#J17wghU;-AH`sDm6+I{=zRm~Yde)eEO6hl@(^1*=A% zgRbkF^>7~TuO!xrvAmpsF{3oD-fMT^-6P!%54d1fN?t9Uc6`nHfGT(I-B1g=JyO! zI%{4dZ&IM@`$i9vuKX^wPd-4+PjBip5H4_Ba>@A=H_k7-ILAd$#WS*`a@qr6!}C2q zbK@m@K;`6TLv&qV65szP`mJ0-?1Hn)4!}9uqfZBM@vTl37iSLQ-EO!iIM;>%@K}Uo z+wn?sW_P$oOvLFs^Ii^`Jr(ctk!9WM$}G}8R(t%=?S*9Y`bh0^S_CPWwNGHX7XWi3 z0C0=ji|#~K=bu5}*;6@a#y#jm4lc_c*Y6XQjZhAEXS6_D7kpv_-aNh!kM{tuPAnTj zT+buWk#t>GNJG`P&f(y97LxeEWhGy~w^E#!k^0`ie6O17EDp%ml@3i|Y!+dyHSGa- z-v;asF~6gA1Ag9p*){yV9iH@#%`VU%`wa-aL$c9N(RXKFWRCN%&)5VOa2 zXn+*(q0Oy+;=t(@lsfcV%k9Q^)b;^Y1S)wfSs_c~Z<4iC{1tHqLH9|_nJqW`~H;kkZY zouK#R3DholkX~aiDsS)>lA`$wLb9y{thV6|L+5Fao?;gXYH<77t6hc7^~@laT=zpiU{a=g@gyO3$8Z*7WFnQnQ}ItX)^KH9rsGS*>aVKz|f#bNumo z>6sD`tX#{^@85!1x2fc7hw*Gc#{9ZKYgc-Xbi~>o20-x1dQx-dlX~dMvhDG4NP1^r zTL}mYoBu-3P(jj?Ci%-5G%t7_`}vn;+h?~(Xut8`OnS!!7#< z_;Y0E?y~RoZiGh0VY-b9IwnF3>9Pt1z+dqvlE0iudf8i@w&&6aW&K0iNeRi%0BAt%87}1l#8C`Y4qxODopoZ_Cbl9b6DEH% zm*lTzLQA^S_ue3uFG8G_W7=HY>sA2Z>mk{{6v7)3t}d6`fbCu2HAzdFmZfj7_3W`E z@0r#m%!k$ig<%GGxN`PfaA|0*XBnZKoK?VSTHBT+M}YCMHH`I>yk$+NK6Luc73{eB zN9??6BIeVLT_$-(gx}jBXG?F4*3w4Wsvv-o+Mx!;_8fNL4GGwWWUY=%iZI4+Bn3Qf z(~Ne?e~E7!lkEQSJ+wUg3K&CI(^gsm2uneX%r>m!Nacjy;;a&zbvRQ}giHKJ8Z-ZX z(FQa|O~Rh_mA#I8k^`&G{rQB{>{Fn?t1}nMTFkiH^lHk zM#n3q_>Z8Or?WJm&5APE!wP2o=E!d4w$WFyd%|4=|F^o^d0wwrpAREAA7gU?0ImH_ zVRT2Pg>{}uGo^!*z7yfKuzDry~IB7oC#MiEziD8`rQw*=WTxdFx&reJWcmM(yil;c_tk?JI?{G z&Z1%3A$nA>xRdFk0+Y^EW+Yh(|V>YtsBUWU7D% zOm`Dpn8nG-dNeQ8E=QLr5}t zaE0F#=|vQi-FS!dG&(%y-_R}>lt6W~0EI$cP5>H|<_9GhNw8WBYpm%J%zwuQ{4hvGD%2V8RB>oA zBg;M$%Wq3yL|cHxJ-`^RumP9&$w+^DywY49;qZ0{fG@&zeiI*+Ah$2TYc`;%g6oS` z*nn{njjjhw_Yzb^s4DLefXn?R-j&j+jTK_pT%qMHZ`pwF_{qrCA&+{A$b+o10&s88 z%&St`Hy`0~Rhmb=YT^YxPo^#i9`>r)fw0^LykiY-Nl+3ObYE%)7FnN5yUC>8 zWj5faL5j6v^X`HerZmsw7+({GLSN#u#u}E3;XP~kgBZ4oB?WulcwGoxq&*(Yk)SHK zaovjWzBNoS%>^H_bCp|=&d(cwcJ8DI8^p3vEE}+VDwa<&pFc-@m{z0$#QOFWG=EGLl_Yflgmq$AlVNr#X@qi^=Egay#4dE% z?+W8eai((j8g;o@EL#fHy`PC?nrWf4Lb`esH#k*X>%@qa!De;IW$j@~b6A1;zZp8M zUuTSVne4_xQ_2+wKyhxYl(lc!%LG~iMGw({-Y5nt%{V94u2!?NsiFW7k%GGR4?}T`au}{P z$18^uwHsQBe*l0Es7gUCid4oJ3s6Ptyo)-e=#OHM(j286hH1?Z zK~#9!?OlCzRMoZropbMUu&| zN_kIRfLLwuiLD@hfl$N%3jsmF2=dSnEEQ3T5R3vL?I*_%}NAI0Iqv7qi0I2&@Z{$oeEfg_CJb8g@S=lBK;r#MF) z=corqD>zgD%r^-VfD901g5Y5}1vf|@mjH=^Z#cs)rlXwc_>dVm4kq-x=KE;{M-4cL zs{!nfZH9*ROv5&&p+3s*E+o_?fE}@!X?V?0v5o1Lj#EI0O8~pzIA?fH_u^%y#%#=d zxCDqhb}$W#buadFBj#i0xm!T|u*uNynBIaaxb6u@5#W8MV~*A$Y{5qxIgUC5*nj{h zIm1k?8T;a(>YZ)?#+?B3^%g8MR9j6*fvW+mM9~YqsRw3V=ye!HrbGSV^&+ioH&4z(Fof zdJljSA0diK+s{Q*N<0EA(OdD9;f?xxZ=edMOCFR`dpk2%87k)JEm3=4KM)lAv_uJ& zQA{NCia=XfN`SkyCTxzP-#!Nf4@xPxM@~r?E1PkS3)Ff`#~?o2qQqxk3?ULOHK{Eu zTRs!jMtl;bv;FxX_`RHlAK6gF_XJ7^uB9^GwJ?Ci0aS1U72H5)6RS4}N_>Q9H#!Ua zY$8iEz-YArU+~C{y=(xB3IYPAu^qG0LI zl~OS?fmD4+Lr_ux-5%dU0X!|IclkYP7^6il{40rs&pg>lBm8#ULhYf&-cd4<+sSB* z8UZG#jS;K;rE(h9c`}img#P$DY>;F4yqu1~e#T)`wt#!ICLD;s;2Qvnjh+nTCvhBp z7?qI?pgvCH-zTMDQUF^j;u(KRZ^fnvEZiSc1$$Dml3Mufm?6byTN_JdJS?XMwF$z; z4yIvA1WulXaw?ux(%}@$h{HB;A)#35v-qP*fHRz7dIav>SCw@9OiF>1Z~>th6hlpy z31FL&+2g4oY@;t+Y*jMx1FFD@m_cKw1$KI};OW7j4vPSfXe~GyW-Nb)l8Jw(5}b-&%0#tDpmg@fr zRUBvSo5A%K8o{qK4M&&}T>{(_#*uFjp?JnY=X^W)1nxB%eKbXY9ZW-I7_Q#39?qan zMk$qHB?Ug`44VusIt2KQCZ5vtoSYU>s!~X#q#$e2Toit`9lej2qu}5cWIy{j%vffZJQ!uCPDk5R6$C}koafWlIA5RFDAqAh=L4pcG1uLEm(Y z8^RYFo|Mxpohhl2P8 zf{y%*E*9r60<}DCn`A`hQ}B!^M!}xHA#33rK(dcp+N|q#t&)KY2*qeBW3ZqW_*0O) zji7INooPY?JQ^h9B&wj%iKVCAeq)<`aOV_T5MY`KuiyeX6<2j~r#~jB1=aVR8KqN(inA5i7ZsD!9u}OO#R>0|aAvZw9Ev5bzDJ z2o`Plbpoew)51LDzVR%2t@#t^c?I!14Fqut4J8s52XUuAAUN-@m?gk_TrA1+t|SQd zc&;cx!M+X1T<~CA#=kCr1}y}^#t;s*se&hnz1#rfJTw6|39A2_k}S0=ea6iwJhmHY zcia^7v8Q&LOA27832*8hg6`zE{A_{l1Q0a-ewKtql?kQD`olxW|L83!Ba36V4Ro5z zwi`S>@A0C3gpEBBV2c0&JOD-}aiWLRrx3Yom!a2d&wv!b7GlLc3`$TqA4INHf6 z)P(@=3EuFTBsnX!JN@okP2_u~tziSQT%Px-T*uw-DB0{_-S9PF76D%n{7OI_g{S9a22O&8L19x$Oqc*#~1wQFw3*GUogu zCgWW!uqdni2~aIy0Di|^{X)q2| z2>h+bp8#nBI-t&N>ngrFKmHVFhE4=;XtHdK1_8OG`{dmbLC6Gf&g8=)J_Ej3mOlaV2t}32fY7Np_xDW{G%a}%O-o*k*?6Y~BD(E9gAM}Z6Jq)( zP{myWghK1)ooIMq0eDkv+r)e&AeTaa0`w8E0gk%_2y7gG`4#GZ@d%8=N8>X7F#);s z@tJ=e1n4gi;5pyMa$QU~4((2rH2e&$^0pMGwu?-IS!(Y^(A(fj=b48d~dEPo(ZHPqifA7@8TwVm(* zpj_Zef9LJKODgF|D&wTd%c14maE$Pqmc4?eh0ocSoZ$Fezy|1iiKL4LxJu9ts7P`x z;N7_gr;EqiTKE94)ew_I=UPKuG{9)805D%0a6QvdB6vgSFf(l5HN>c@M%~PL&?^ol z1X14>tm!bilgzqkfFeSLV*Tp`tBI^PRE*aeZ99=%*HQn_LezZk=7bSG0Q^mW0KGtP zUMCx%+u{E@0n7djxar0OpE3h8^%i&mR5JV756#Qp!0ADw(fUSNLTytYGF>P#Gu}^Q zcO$?=!K2+vCMt@Z<*dufUl~EO$!J5}wGXFeU-&Or^u*2h1#3`1LvmC2Cu12%%dsiC=;B^akK{l06?jLQ^)|YHUtYN zsEw!z;G^DVgh7HRY#p32)c@C$sJY@sX!{Q)^eN>9!PP%DfWaP+0Mi6()CB7v{A;Z_ zXjk!-VKks(=Ncm0=U;jgrw5jzb=CT$IHoQY+)4v=C<#b_8wCk)lr!w{^9j75d$Br% zdfFC-4?+LOk?{8UJ)hvrh)HPt-QuM2QIr`PY6YTy1c8fD1`Pq;B4`XgrvJ--@B!2D zsEJ+!uL-I!Z`r$I`~0_OP&;KN&P|;KcB%%+gvSNj_}m_(pkz=2%n~gBTFDKRGaXf& zVT#G_qALXn!0Q^&YBIO3VcsItjGPQ@Zv~PKZyBm^@8BpTT zrQ)Z$`MkCxVPp!eG`#qgNUs6TQS<#NNV{_iQYKyt+B+ZY>u;g%+=J#7Yk`(lBr}%k zt-@*f4~3ZD9=nE>c!g~OHLGXVex>~vT7wS33C8}8W=Kdhq8*bMy0GMxaCy=kf z@r8pz%aLG47@gZ6?V+GDDJYb+x2?pRvqZJ=yY#b^YU}agFYtjc?i{eTcD)D%4Dt$ zt`_LPdrULsPWMM1h)_>KAp$JZy|D7Y=57ORIKXt=riFL0^cBIa+B5-nG7a+$YrSkA za06b4*B&^;3{23%DU=IP-tvENE5D2I(VjP7~3vSEHBhkVdL&fE415QMsU5671%c9_&?M8r)nT`j- z2s}jJC*Vyw!Pjw)o76_kj&Oc2CNyYDfo?shTrKesE*PpY6Ow6Axdh$M*;-HNzPEo3>@$g z;{Z2s&f;U@*C{y(BXq_&mK!RT7~ZJXQ=UW>Ja17rUWfnzRW%1HxQ+^Lpwg!;4o6X2 zESA%7tK_k@;LDkg6^1HYsKM+xf3}5rnGq8p=*s1+LrWa+Z6~#1tcnsMVUq=_FH*c? zXn31xSkE-eBBZO8jEI~(aV0<~ZP9rPG1IbE`0_}UQN_m*t+Cup9NC<2#2fqQsOnxaF_;& z`~)zFPz>|kyd6Vj(|7P(0@wsaplAd~6F3aCRXU|;>!q6tf*eAS3xYgC&=(Z_3B`8_ o#U+$tAd!-8K4KaSa$!IGKebOZR<0hj0000007*qoM6N<$f+K%OV*mgE literal 0 HcmV?d00001 diff --git a/tubesync/common/static/images/favicon.ico b/tubesync/common/static/images/favicon.ico index 04e6460397f383f639eed1de340011ce7b405c73..cf2e89adc6f2eadcc021e7474f7957dbf45edf26 100644 GIT binary patch literal 22158 zcmeHPUyNMWS^w^=?cGH@T-&j|OQ0R6ZR}0jFm~<6D$P|0rZk8@53z(ILHpoMln5k1b%l(0Xq7Y~s6wb|>>Ws@1ZV;A z`+eunJ@?Mcdi?-J>YjM!p7Z@b-}%nJ@6JXfl0k{%7|%_zHxfA`A|oTF{XW{S;8QHx zc0puzK%`VM?ddHdzlBe^Y}-F0@|~X*sa7rhPLW^UCDLeE{9ci}?-Rj8Vtk7DP;bAo zcV|KF+4)Jich`QoXXK0W*^wvZb0f#`IW48pKau^Te=UbT`F%O|D>r2B%l|5GeEnm& z{`i*C5a4O8U$BchLhq<0->9e%kqW#<+A`@ zh@mOz*RS=$>8BBVO8Bhprvcf!^G>-3e!6$$sC;(Ul-xJ+W!d+0@X?)b$^D=BzWh@0 zALTcGeN`4_e<-hi{UiC__kQI4)XbNP+)q%O|Ed@>)aOs`-_vZJDa)Z|vm!D^e7VqU zz9{k}>$5;y5CIEHbxZT26q;99KVN9pwrqK6b%l+1x_o5%rOxV=c}O`_JllM!)42(r z>X0O?cWyx85Tvl)dAoVq*RP^(=sVvcefbD!zT2EXTRv19Lj7IXFc?o?9BBUbyRXu& z0&JS5(q==pG@B)SP%1LeY%Z}Eutse!$s_a4x#-|oKxT^~)AObi&AA6m*P3wu|7zhl z7x5|Mv-UV+?(E!#&o5xCKaX*K7<1v2+&9{geWQOUpTF~)atLEReQZ^J_r(w8FW>lB z{t4s!qyO^r0a4ji4i^sA17N!%(RKv1miF^W^6Y+*?R7SvKYG_^5b@2~vfPd4>8-JF z3SfejB5<6?S~0HeOw3BL~o?rsXylr0qWlLnhHbJ{HS(3_@#N^X!1+SGx}{xDu6I^f2w09L%R_ix?-)Q^#*4$I-MM)M%8O$<34uq9%_r^h zFsDE1QLeF_;xVn;(ojz|Qul})N|IK*XhDJ*JJoD9nH$lDkQeuVZ~up1&w}pPWZT2_pzW#+n4nvO1K8&R;qpiZ+D5AZ zgHev8h}H=XP`mjYd&GffX+HOW$SzY)o{a^20!r(_t)$s&;mIr-IwmDbjok2Xw-Swz z7f8+-5@#gF<0KgM7!b;Wf^S?gkV7- zoRdaNO$J*sFwZ*S9)bPzvh9NvR)JuMl2`?+58mHmKJweuD}8nN)E0u<#XDlEn!Ap8$`>9q8XyaMFnHrtBr7 z;PW!eYDQA`x+tfZ>VmIL*zpPsVZ#}T>%51&GKB})gNXnL9Lvf)m( zSX67DPU*U*bd}a)Jf3#LvCTbR>?lWb48u;95pBdX##2#}1=jJ2w zxm{J9rCz`u^9Q(F{EhB058V6DGWDfZdHLcG<&AIroBaLXrS}V-A%haj)&oxj?R*v1 zAVjD0VBc1JB#(GNuA+E+>DfGoW3%W8j^vPYC-u1dz+JixfoeJ=ID;)~!~*6J`Y4+` z{`tohz_YO_vzTVs%Cs?eqNr0y#3K2aBP=ou%8R*#BX?Tn2p!UP!w|@Dibd@_cOiu+ zDQKK|maGcUUahl+a>OF+gKVY?xRJ1A(Yz2i9}p{19!~*71fEy?<~*L4B2`dRypm>U z$VV5Hh>!Q8h6_(v(8ELUm9ld3`55c38Z8A0yB`XvROp+ZaPcz_&vtegeFU(O5(8kcqz(zsf4g9HUZ0&joBl1-p41Ae&5cpqR)<#fET7f?-7&Qb4uG>eA5cmzfzjJ_`)%|M+>_E zcle#JDA7Z8hvc)W1QOk~{|K80tz6bkDH{SmTOHgz=Sr4f$U$G?KDRcXt~+3XjyvjWlPcEH^YzBSIv6}Xbp)5vysEanNuEQ0O+hDYW*|?C z^uUST69#(W)XAeIT5rmsZrY?hdl<-ifN4Fpm0DuBDFljra znbfn7@5YIODCBc8rOlKfIDDEAqMuXAPzr>}wS+8BLpuKX+%57Gwp)CRhNPzc3>mQF zI?OpLLDPQ!^InC|}l4 z*IsmYS9y*zRGAwyrL3mlD;jd3>{C-E@t^}D^P(2o?1lpePlOW`xX!hU><<88+9aUX z{1vd{4tAW>VDSF|{c^7(`EKE6DJ{Bx?}z*U*NK?@^vSK{g6y!oX`F zCb>yab<+}Zkv+EZN=gj+$=<1oQY8>E>`G3;+@hOSG~5?!Jl zXwWt2Po$FwZ~tyw>7v#gXe>JZ6__?aqqIBB)AiI)f>@PEV}_93HA%-WI*4MDJ@Em;@++~O! zW7>8t`d}C^vNE~=`Qfsemv0j8s=NyOL7&}Ky6Ks4H}oJKUce}?E#KzQ`NGV~H<@}P zq+32;_iL%b{^5&|zh-~a4p%7uBEHN_F+#fKzi-7O?+t%qTE=UP7n1ruxb{Kx1UIMt z@!;M8s0xUeiDj<*P9vUqd#coTGo+!TE9n4D~j@CsSyaKAd8@P|ahZ zj{D3-#Fp0+LCy zj?VzX0W)hY(U$%LORA4WiMHr#Kn;Wn6r>Sn=rfMz3&LooWZYw4Z`Pf>>s+dGJ6;7Q z>;Sph@3^0)XOFi)9(a;scz!Vlj0rXoN5K?+Efd1TCv9|)PH}E5p&oNYSYCe5y!A3I z{l>yIy<4&w-s6=7U4c*Ru!oaVUBh+RK0Lyo7}a ztv+W%h=VbRnK<@Qj5QtVT#xfgmMM)NKd9KluxSL7Cc}d9q5q*`+`%#6Xx3db`$WLg z|0sT4(-X4UwX?KrRULV7BrdT};W81h6;-x=`7q`#Ch@jjUDgfSvP5+!r>FxGF6<6t zk9Wo>?{p@*;M4mZRr*}CvPqD-RA)0l-3(PnA4%ci)L^Q`4Y`}4OnO)o9hgp)qV}i` zqr{&+n*rnYf>Jm*m5MfabIgTXqtDa>4ubEP3IM*!E^DO3@%D#~oqEzBF7^Hm1d+$7 z*%#|Ncf<8!(@OiWQD9iSt5bq}tyS{U{b4^(lWDigo*`KBG9=kXyTTr8@v|vQk#9Za z7}iOj%pEOqJmVdCNqyV6obN{Vy)XW@5Vm(4j|~rOcwoZ=|K}cHp1VP<+|t(ky|&1n zo!ey$zuCTL*FNOAe+|E>cnW#$bN2VC=68EfRaRyGD<8`1fA*2Q{q6L3$hWm9-Y)Sn z@}FBj^-$LyyIwiCG@<+Ge{S<$KR>u}0>jt3(${&pZSbo9AtCnz#XM=xwmDNlh?=k? zf7Iy7lL7KTN$d4L8K`HF>u6~Br~n>Jqx4+24qlSbZexLN-%+8yPDV>s1ivjjsK&DW z_V`PV8&9=kt^0!$-9F`N$zeS!dJ9sdPrkkk8q&^l3KvR>UZ)6Ji_BOd$Gg>RqP zX9G>`?7Dn?`%^K;Ne4~(BXkGmC5@Jw|A3!#n64*(A`Ts~{Vl1%FGHtYCQLu( zyZAi7TrMDF+=EO4#7I!%kelgWUZ5uQF&u&=0`#M{t#QMK+%hTA)i4H%3Nu4^s|mt1 z3e_RQ?2EhFQE>1=$m27W8b~;e0x#iaPLUeE!R0o?<{Mm7p(Yyh5R)6HYIY$^0tX~% zwL!9M@)1J_M(tN{HBDJEHG5I^nGzytzR}-%c4h>eh5_ipXbQx=pRd|f%5VzqQ)9vp zy$!~>p^nEFdN$FAD*zv+0cqLox7KUj3-$loUn z7L*MGfENw1UrbCuWchPhW}|_BHiH6weG!tIb{YM>M^U2<>2oV+)QUBaEPwA&gwbj? zUbMk~<7@Hv6i|fQ`NClVgO}fQa{BXcC{kc&HKL>GVXM?8+EM*SFevv@hE zd3N)6k77ghn^~9N^m_1j30P45Gy3N!nez-x=*6E8gNq0ork=}me|Q|}!=DcWO+{nA zm+1arFQW%~>Ce5zN-jYyQ|(1gq+Ei!H$VQoI4I`WHkQzQK^%sq4}a&KfCzC9#iM5W z*_GU(`|)=i0iI?TALY>@*a{6nU;cMe0p=(kcb; zwG>G19>2`UnV~Xf^Sr?L$@~y z6JZCk{3{^}aX-voZtpl;>!k@9yBJos?=u7Ss$mMiQ@=HlV` zvm-~*cq<*_@?BCM#E$kclb|8T~c96}uD4zf7``lB$~ZpLsdKv!WB%R~U{s$!hselrB9 zgfm8uBf#c<*`5`#r~?m0W(+gCc1hKTQJv*w>ojN>s2YRlhg$%M!+iqQ;lFXVdY1}0 zb@cc^$qXUQLdm2yvvSC8Cod_pyAFODtwSSy!?f9^{&A2nzMATGzT{i=fG2>V=&xKU6$ie9hj*Y6r;}4p2ii3gqt z-5yG?3n_*Hoj92N!42rho$qwWu0JwV7ifs!*Ez?go&!aa!EdV0G*|BSzQ36p}n`9iYY| zo`yr@dg{+O51MejZGQZZh{AIF{7I`!_uF#IO`%txp55x$GmA_w(%!K4$s#4diQyvE qo3;;h?&O2JAz@D+^#2dAchg2?!vh;0*zmxH2R1yg;enqT5Bv{4dL^&` literal 45806 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�x8k&YoPW$Cc60MW8W|LcUW=IK*CJu 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

Oe*YL2T-vKMJbgf|(xw47)G2_YElt`sZ{w4|wH~ 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 literal 0 HcmV?d00001 diff --git a/tubesync/common/templates/tubesync-coloured.svg b/tubesync/common/templates/tubesync-coloured.svg new file mode 100644 index 0000000..ea87b83 --- /dev/null +++ b/tubesync/common/templates/tubesync-coloured.svg @@ -0,0 +1,83 @@ + + diff --git a/tubesync/sync/models.py b/tubesync/sync/models.py index 27e116c..bf9a7f0 100644 --- a/tubesync/sync/models.py +++ b/tubesync/sync/models.py @@ -5,6 +5,7 @@ from datetime import datetime from pathlib import Path from django.conf import settings from django.db import models +from django.core.files.storage import FileSystemStorage from django.utils.text import slugify from django.utils.translation import gettext_lazy as _ from common.errors import NoFormatException @@ -15,6 +16,9 @@ from .matching import (get_best_combined_format, get_best_audio_format, get_best_video_format) +media_file_storage = FileSystemStorage(location=settings.DOWNLOAD_ROOT) + + class Source(models.Model): ''' A Source is a source of media. Currently, this is either a YouTube channel @@ -295,10 +299,11 @@ class Source(models.Model): @property def directory_path(self): + download_dir = Path(media_file_storage.location) if self.source_resolution == self.SOURCE_RESOLUTION_AUDIO: - return settings.SYNC_AUDIO_ROOT / self.directory + return download_dir / settings.DOWNLOAD_AUDIO_DIR / self.directory else: - return settings.SYNC_VIDEO_ROOT / self.directory + return download_dir / settings.DOWNLOAD_VIDEO_DIR / self.directory def make_directory(self): return os.makedirs(self.directory_path, exist_ok=True) @@ -483,6 +488,7 @@ class Media(models.Model): max_length=200, blank=True, null=True, + storage=media_file_storage, help_text=_('Media file') ) downloaded = models.BooleanField( @@ -656,26 +662,29 @@ class Media(models.Model): @property def filename(self): + if self.media_file: + return os.path.basename(self.media_file.name) upload_date = self.upload_date dateobj = upload_date if upload_date else self.created datestr = dateobj.strftime('%Y-%m-%d') - source_name = slugify(self.source.name) - name = slugify(self.name.replace('&', 'and').replace('+', 'and'))[:50] - key = self.key.strip() - fmt = self.source.source_resolution.lower() - if self.source.is_audio(): - codecs = self.source.source_acodec.lower() + source_name = slugify(self.source.name).replace('_', '-') + name = slugify(self.name.replace('&', 'and').replace('+', 'and')) + name = name.replace('_', '-')[:80] + key = self.key.strip().replace('_', '-')[:20] + fmt = [] + if self.source.is_audio: + fmt.append(self.source.source_acodec.lower()) else: - codecs = [] - vcodec = self.source.source_vcodec.lower() - acodec = self.source.source_acodec.lower() - if vcodec: - codecs.append(vcodec) - if acodec: - codecs.append(acodec) - codecs = '-'.join(codecs) + fmt.append(self.source.source_resolution.lower()) + fmt.append(self.source.source_vcodec.lower()) + fmt.append(self.source.source_acodec.lower()) + if self.source.prefer_60fps: + fmt.append('60fps') + if self.source.prefer_hdr: + fmt.append('hdr') + fmt = '-'.join(fmt) ext = self.source.extension - return f'{datestr}_{source_name}_{name}_{key}-{fmt}-{codecs}.{ext}' + return f'{datestr}_{source_name}_{name}_{key}_{fmt}.{ext}' @property def filepath(self): diff --git a/tubesync/sync/templates/sync/media-item.html b/tubesync/sync/templates/sync/media-item.html index 836a6e9..48c04d0 100644 --- a/tubesync/sync/templates/sync/media-item.html +++ b/tubesync/sync/templates/sync/media-item.html @@ -32,9 +32,13 @@

+ {% if task.locked_by_pid_running %} + {{ task }}
+ Task started at {{ task.run_at|date:'Y-m-d H:i:s' }} + {% else %} {{ task }}
- {% if task.instance.index_schedule %}Scheduled to run {{ task.instance.get_index_schedule_display|lower }}.
{% endif %} Task will run {% if task.run_now %}immediately{% else %}at {{ task.run_at|date:'Y-m-d H:i:s' }}{% endif %} + {% endif %}
@@ -80,6 +84,7 @@ Container Container
{{ media.downloaded_container|upper }} + {% if media.downloaded_video_codec %} Downloaded FPS Downloaded FPS
{{ media.downloaded_fps }} FPS @@ -88,6 +93,7 @@ Downloaded HDR? Downloaded HDR?
{% if media.downloaded_hdr %}{% else %}{% endif %} + {% endif %} {% else %} Can download? @@ -98,12 +104,12 @@ Available formats Available formats
{% for format in media.formats %} - +
ID: {{ format.format_id }} {% if format.vcodec|lower != 'none' %}, {{ format.format_note }} ({{ format.width }}x{{ format.height }}), fps:{{ format.fps|lower }}, video:{{ format.vcodec }} @{{ format.tbr }}k{% endif %} {% if format.acodec|lower != 'none' %}, audio:{{ format.acodec }} @{{ format.abr }}k / {{ format.asr }}Hz{% endif %} {% if format.format_id == combined_format or format.format_id == audio_format or format.format_id == video_format %}(matched){% endif %} - +
{% empty %} Media has no indexed available formats {% endfor %} diff --git a/tubesync/sync/utils.py b/tubesync/sync/utils.py index c3f82a2..63b5a9c 100644 --- a/tubesync/sync/utils.py +++ b/tubesync/sync/utils.py @@ -96,10 +96,8 @@ def file_is_editable(filepath): allowed_paths = ( # Media item thumbnails os.path.commonpath([os.path.abspath(str(settings.MEDIA_ROOT))]), - # Downloaded video files - os.path.commonpath([os.path.abspath(str(settings.SYNC_VIDEO_ROOT))]), - # Downloaded audio files - os.path.commonpath([os.path.abspath(str(settings.SYNC_AUDIO_ROOT))]), + # Downloaded media files + os.path.commonpath([os.path.abspath(str(settings.DOWNLOAD_ROOT))]), ) filepath = os.path.abspath(str(filepath)) if not os.path.isfile(filepath): diff --git a/tubesync/sync/youtube.py b/tubesync/sync/youtube.py index 562da19..637df6a 100644 --- a/tubesync/sync/youtube.py +++ b/tubesync/sync/youtube.py @@ -4,6 +4,7 @@ ''' +import os from django.conf import settings from copy import copy from common.logger import log @@ -11,7 +12,6 @@ import youtube_dl _defaults = getattr(settings, 'YOUTUBE_DEFAULTS', {}) -_defaults.update({'logger': log}) class YouTubeError(youtube_dl.utils.DownloadError): @@ -32,6 +32,7 @@ def get_media_info(url): 'skip_download': True, 'forcejson': True, 'simulate': True, + 'logger': log }) response = {} with youtube_dl.YoutubeDL(opts) as y: @@ -46,12 +47,37 @@ def download_media(url, media_format, extension, output_file): ''' Downloads a YouTube URL to a file on disk. ''' + + def hook(event): + filename = os.path.basename(event['filename']) + if event['status'] == 'error': + log.error(f'[youtube-dl] error occured downloading: {filename}') + elif event['status'] == 'downloading': + p = round((event['downloaded_bytes'] / event['total_bytes']) * 100, -1) + if p > hook.download_progress: + hook.download_progress = p + eta = event.get('_eta_str', '?').strip() + percent_done = event.get('_percent_str', '?').strip() + speed = event.get('_speed_str', '?').strip() + total = event.get('_total_bytes_str', '?').strip() + log.info(f'[youtube-dl] downloading: {filename} - {percent_done} of ' + f'{total} at {speed}, {eta} remaining') + elif event['status'] == 'finished': + total_size_str = event.get('_total_bytes_str', '?').strip() + elapsed_str = event.get('_elapsed_str', '?').strip() + log.info(f'[youtube-dl] finished downloading: {filename} - ' + f'{total_size_str} in {elapsed_str}') + else: + log.warn(f'[youtube-dl] unknown event: {str(event)}') + hook.download_progress = 0 + opts = copy(_defaults) opts.update({ 'format': media_format, 'merge_output_format': extension, 'outtmpl': output_file, 'quiet': True, + 'progress_hooks': [hook], }) with youtube_dl.YoutubeDL(opts) as y: try: diff --git a/tubesync/tubesync/local_settings.py.container b/tubesync/tubesync/local_settings.py.container index 3b71cbc..c51183b 100644 --- a/tubesync/tubesync/local_settings.py.container +++ b/tubesync/tubesync/local_settings.py.container @@ -25,5 +25,4 @@ BACKGROUND_TASK_ASYNC_THREADS = int(os.get('TUBESYNC_WORKERS', 2)) MEDIA_ROOT = ROOT_DIR / 'config' / 'media' -SYNC_VIDEO_ROOT = ROOT_DIR / 'downloads' / 'video' -SYNC_AUDIO_ROOT = ROOT_DIR / 'downloads' / 'audio' +DOWNLOAD_ROOT = ROOT_DIR / 'downloads' diff --git a/tubesync/tubesync/settings.py b/tubesync/tubesync/settings.py index 2120836..3facb96 100644 --- a/tubesync/tubesync/settings.py +++ b/tubesync/tubesync/settings.py @@ -98,8 +98,9 @@ STATIC_URL = '/static/' STATIC_ROOT = BASE_DIR / 'static' #MEDIA_URL = '/media/' MEDIA_ROOT = BASE_DIR / 'media' -SYNC_VIDEO_ROOT = BASE_DIR / 'downloads' / 'video' -SYNC_AUDIO_ROOT = BASE_DIR / 'downloads' / 'audio' +DOWNLOAD_ROOT = BASE_DIR / 'downloads' +DOWNLOAD_VIDEO_DIR = 'video' +DOWNLOAD_AUDIO_DIR = 'audio' SASS_PROCESSOR_ROOT = STATIC_ROOT @@ -115,9 +116,9 @@ HEALTHCHECK_ALLOWED_IPS = ('127.0.0.1',) MAX_ATTEMPTS = 10 # Number of times tasks will be retried MAX_RUN_TIME = 1800 # Maximum amount of time in seconds a task can run -BACKGROUND_TASK_RUN_ASYNC = True # Run tasks async in the background -BACKGROUND_TASK_ASYNC_THREADS = 2 # Number of async tasks to run at once -BACKGROUND_TASK_PRIORITY_ORDERING = 'ASC' # Use 'niceness' task priority ordering +BACKGROUND_TASK_RUN_ASYNC = False # Run tasks async in the background +BACKGROUND_TASK_ASYNC_THREADS = 1 # Number of async tasks to run at once +BACKGROUND_TASK_PRIORITY_ORDERING = 'ASC' # Use 'niceness' task priority ordering COMPLETED_TASKS_DAYS_TO_KEEP = 30 # Number of days to keep completed tasks