N?W=NHg=>3LDbeoTDF^FShRM?^Ud?f?YBiRIiiXM7CCI9@``A1cV=iXcmIUU`:S`46ZGV;^R9YLTYKni7SfAn1c:B@7N1K`2FKknSO_=JgmB[Q5N4=>hl@E[OWGnn4UlkWEX6L=b?2L>\X6gN[cR3VOU0XHemHXn@iCBg8CJ8gJm3bc>^hUbmdXk]Le?VakBcl>HdED12T861m^22DV3N\a55MH1TJ;[`1K0@`jF[gbML:X8P9V=IMf?k=RLWZmEdCW22Sn3L\Jil`iinLUTF;ma3iYBLSEfHQ5jmmG\4JYVT\S\IbFd8oB@OHCPWF;P`hHfUenbYnEoc1Xf4[9=`a31@YajVKab?8mKLk?9gUUUX3^biSIC@@F4=4nKXZ]=gakb7m[P^eaaGIVHWQZEIU>X[LkM4h[BQ6o8_28NkkVJF@EMW?Q6U=APC7X]LV386\J]ANI`L0eJ[3S0HFD?n0F[Sdon`Tm^_DM4YdS_\6D?3J^i;G@<]m6:5VYUUH5JP[hAKTM1E60aaN>H4E714^9OV7FTQ:9mJ73NAo=h;[eR1]dfV=>WZeXI66Zed]mTPf\M_03P<1LfVJ^mW?OQ]GQ_S;cdD7XiRdma=a]K04G[0j<9bo45kJ1QAI]k5[WkTf6_>UhebfO4UKNi6UaFXdG1fNR3]3[lUB=a?cgVcoMG9Q5U5CVgU@j:E[mRXO>H1:1bd;]0S[naC3\`0B?7P5f]Sf@4ImAJRS:U:Xb;abOBJhI:J6RGC78ZhSa?T0>An;UhFm82:RbAF4jkITQNoJYW?dRQhXhC\FbRA0K^e6k]1^dQ^6l;4;c>NX19n[oA=Jjiag81RX^eFV0QHe8QmSGbY`eH2G@GNM\_D6oMd:NOLNHWNk[cGYZgV5o]5>R52gH1_::H@NnTGJI>dZa9I?TCWL3f_SLc6`PAJYg72FE=Vl=RhWQWV6I5^>22SSX^2NIUdUVA@3?fb17]fH=Q0K_;=oN;>j8jK_o[GHAXMKF?RFOYSPP9Vn[cnD@J1_f_?AKSdfS3VceMAC7R[9c9M]og_E[IdU_TC77V>mWF3\Z[_b4=m?kkF:38Mc?R2WK>X@fR?81aD1ZA<;n@BgOkU<8bcU\kG3`ReW_I`\9nVPQcG:[XbjNXoIPb?GH21FI9E4LkFF]M6ZLF3f<:KbOT_4:XoHWC[2_VF`UX8G4^V_=8B?ZO8B[VmcdiY`h_fgV@\NIYnWO\MjS6309]3CAj4^nP:a8AK:f6iMe9@h=;gh;2lKjS9KEeM[N8I74hDFacHalPFS]E2BI\Z[^TDE6SBM:1Cbb19IHGVkNa9bHO7U88h1?1oZ5AmR]@XkL9;Ff:jSnTofRN43nlATU@_LDUC6VlEN;97NSJP4H1kFP[g7]RHJd4SESOCNRIfO5>?If?:hDi`0DNh]8`VVUood[R@>RL5WAEYXA\0Q2H^P1:?bNI3G]H8NR6L<^HfNldIafkO6`cH@mZPdERo5WDh?2:4YU:ji:[o`3E6ehbES4m=RE=FUkYRcj=FfCc4GXBkDDioV?P0D5e5]@PlE:1X^1]HGk08T^6A77`EDKAanoDNh[jGA4@dJAgRE74f=4JAaNR0PLaDUl__[E=[nSogI9GF;e]K@kbLkk9kOFRe]0DA^KCa35=9iJEE0C[gCb6bKPnU<5h^:XCYMW\IdHaL0dC@>?]_j3G_2nU>fY[DQJ[\R0nLJY7[X`iQmQ3TeFE6hO4m85`VbbLYM`W1J[B?=;?4BDM_1hmSSDT1OVJWV3]4;P4hg6gJP\=M3=AL8^39GW6mD\MhK9X6h9:1cTkcF:4I[SYjAg9c7OKjH7c9g?_h6[aTITR6ZDdVaGFig<`4NP?>9d>[JZbaJfld@[SOecCe7EgPn6WoIhfYEJEOSXJ>\E7PI>KE;GigAf^@2VcC`NnE9NfCJImCJWNh`L^Alb_RZ69AF9=TSONT6WBnHI\6cSJi0]35nl:ZndAJ9_bi>1@e5_IdM:ohS>HH4B4AUCHRc[eKCn0lgHY<`o>JP8SLjbHVaXQJL4hSj_e?RE0=jWaXR_?Da?1J:C[lL??:\;;8>=KA]TTGh[:kkk9QAi4keJ<5CCX>ln[D7TJ:?IF;6dCOQ\T1QhCMf;8E3[HmlVnFEc2kFjhN2jMD;^2aW6knkjam4bm:NY3M9LF_S1Mm5[K2GW]XFHT1DmkH]SBU\N76a[l<;AmhE`SlNPEO`jW\VlbUcLh`Qmm2;BFc68jD6[E\>`cH]7\bZW8bME]>aKo2\MXRM2QFA_mfDNGICaLVo_MA^l;P6EVHJl_k7ae@R?NcMaC:4924L81CGj>>\5AX8J8bm`kXhIfm2^i[7mKCiaP8[j2H`D@fKG76o\TFSd5d21c`beYCWoHW4gG_hFRYeoaYjHFjVM]caKe]Tien>4Gm1aROUF1KX6[?c[=4WjaESSHm`70d_F`^@HE4G0N\Glb6kE?6JmX\1lU6\7W7E4Z`J`cCH3C0]9J^I2;]1fh\MW>8cde>CaG7lS\5kDQ2>bj\e1V75J;G7TG5EIk9BNk:BRXnoXBZhO3>k>P_>lMB4L@^a==`O3W8kAj><2@bXOMEWI2j^1fZ4Gh]=0_MH:c:132?U:1e=RSn3C9d`?L7SA_dRiEXg>[;G9W\n
\ No newline at end of file
diff --git a/proxy_template.nkind~ b/proxy_template.nkind~
new file mode 100644
index 0000000..56a7545
--- /dev/null
+++ b/proxy_template.nkind~
@@ -0,0 +1 @@
+Nuke Indie mode encrypted text (commercial mode uses plain text) URFRP09]GZT32L<][1kB3Jn^kgde@XCJR9JX0f\dbF?IdTI<a=6gK0i5nb5B8=2EFaYU>kKPH`AmkOf@_Ik1Ea27Qm[[=b6]Xb9]D=CR[a6L;>4UVCB8ZOD:E:FgA<>`4R3obWhG?m3N?4]aHB_BYSNRleg8XSO^CN6<6T;S9H8YZbTKB=AiH4`]E:[_iX^mKb@h0^LEL3`D<K^fC?XJhSDo9B9cjnSW9M2G3DdXo=;OFAX4YePF4kImo\nR>iZ=Q9=WS[j[fITbhdg>K09KG=TZaJ4FIeK=74TgC9P8K0;g^3MFlDiEi^4MPaHiPOVbSLXhQ^40h>BVLn_>HQ]VMRS@0]?OZJ;MM@lVATm1?XF1PR`j:7b^f>mYh24dRmbINZ=cQD?SS?6D^@i4AciHR7dS5E_oHDB:;0:07HET@k6BRcaGFJ`nd;ke@EAaFP^WTRMhYJ1RfMS8bO@]VP3gK8B^@HDM1:>Lk6Q88M84d>h=GA=_MklNEh\5GJ1hS>V;H]l9>fNl:e_OkofFGdMl66LJ_]C43>[hJC:HTN_V1SPY\B_ZaTERdP]7k^0?L[ILmS4N?hhdCjXa]U7:c3JE6V<_ZCB[Mm8?MLi02QoHdL@c?Nf9m=Mg00U]@91[1IDFUA1FPR=JY9lW]V^OV9MHkgH\bG@Z06EQXea[IcC9EM@MSl?Pe>h:9aYOK7U]J>EW9^:94DRP[gh\lZM5Y760dA6SM1BK<_UJ9lnk9:jMR09Nia0[i]e]aMOZ=4o6SD3b5GIG997H\A9kKBcjK^f>S\d:Vmf7W5F6]W_=7R7HPZP45nIb7o659hVjIjMAIbJlQ@>?O_X9VIG@?QOL`QFiUI?]H@N?TV]RP?RCg]4O^1jG0h1SjSaLAao@`7PEI>0X`oQhINXgb1diCQLdLGoBJnG;C^E:;2P7AEgXRB76R_4C_bnGcR4oXl?3OaJ?DnD^i`^Pbl_[5EMUnCng29kZY\R_W;CVVSL]?l\`Un10_NUf?f9_K5l]J3=]ad6FVfF[=Y^Udaa3T^UEY59f^`AYbDJ3o5BM84AI;0E;oG?J9L;fOjm@CB\1l0KX=:hlD\_a>mK7Pj1cb147jWB;[khIfT^B?VOa4LI0==RL[D<^T64h=ahNJomb5e4Xi`>AZj9R;d=VSnPhDJLQK^gEAKPQ2ck1COb;5a5b]0KoDhT9_9NSE4\EM50=[Qf4ac;RPfIH;hmQ>TI25Wec=9eCo2N2VAb57=6;MoPNSkhG_i4P\aGYW6:7eiL;7AL5gWj29KK^iFbHmEb@PjR<<4^U31eRYKMD0CR`=GfhfSUSN`JL1j?60?2aWKSMf0P`:jN7S?M0GG?T9G4?eMBKOMgUYUcUP40X^ZFSMcaCT\Z\VJJ]0SVIZMY]9[5n7n:>:8QE[1^0k4n]]ZMg3N2;P0mGK>gT9N^_:YIN?_1kfOCWcl6EPL12K45\m7e_ZFC8XCZ^4f[:mm3O;j3\WLeL>Y>X3>OonG9lboV3:>7L`6gedel1;fmWIlC72nl3b^DU;B41XV80;TSR36VB8UP]f;eM3g=cC;ZP0LBQN1P^NioQl4kT2k>PSc`JMHQ8KhLMV?OZW3IG`O91Cd9GMO@oKTR8\K@HB6E9nJU4nbK2JEP94W5ZgXUV8=9@R_h;Un8J_D6=G]Cj3k666FK]V:PD?<>^?mZZh_LU6PVR`NC\a:2JGlchL?k8bncB_VD>2XlEk<<193H^D=ChkJA]fd>]9CY>QZ`@Aeb=[iVMTSJHO3VTL;W9=JaCiTU2RSGOf3Xc1FOlH2if>6Tbo>0\;DL3O1MEkMi:hS_[@IhdgW[EQ4k]_lRZL`2U7JINfK@1Mm;W4ja37HRD^8j`GIKGXHPHR@O9eAB>=omS9@k[PbKYIfkV;YOB^6gk6_i2A@Lo4DjB:D=cAOPEA^<_8d2XCn1c\F\md^ZilZ2US?8A=CNj0UBHLkK@YMTL]eMchc`5UB>b_M\8gb>m;RQ]6j8>Hcb<@4nfX[VOC5ROTkWcO1nQEoVK]o?UlOii?98_@nIo5=n3oY_5jjITBBWEh=m6MQ@[I;2U:9XA@2>EOSgG\b@N2GFIC0iW1kd^iWJ6@c1O0Vd=EEbo7XOOIn57Y`fD^=MeN:JT8`Ckm;;OH4g?^SZO^QZX9VPOoGCL]SAJ?i2HjJMWoISgi6^GOkdVM5@;VMgJG?GoD;=]Ci9X:_n?m4UgJn[_g1@CG]4:P\cWSc4N8Ck1?CAK9:iBTfOIXEddmaQ\HaST8VBOdaE?kb=DcN]nTA=6dS91<4ZNj[=\EocEKZJG3JZ6KnNHQR`GjnIOnon<]O7=BC\4\Xm^6G\jABVdjDVESdFi>\JTLgclQ]h@40hKUFJ^8B?20Ed];`T4V5hP:3VUcN]=R`h1ff>2_80`F2RBgA\\`<]cc13S19`\`J4KJHaK;^U>Q1aYj6PV1Gc?i4PCdoXS\5H;C1B@ZH5>X4nhGE?]EIVQ?`IMgBH`JYj[?Tg?nmI9Dk4jD2IjJR9C_C9ROkM0omolhY[:ZX3m4]EnISGjINMXW6>VaFdbN7VS\0]Vf_o:RJ=\QVZ?`;OF:G5[YPA6ZBIW]FCe?lcd=3E=L>dQlLjnmWOdLQY4hLj7Nc`[nACA=amI0ZD_lPH]2nlgg;YGWHR[^d9QZ1_5P1NgO_chfe7KRUER8h>96LeU6>NBUUKYViV\aMam0JD:;lI6m7]1:3ecYB8eTW8B\Jj9X;bC4?E<70lSfBREe1@F?CE\mUDjmk0K:n8V4[Vf9loI\?j`^XVDM7WJPe7n_SbW5X[g@k:>ica8NfnX6j=?nbDdgdFg07I^_Qod9]WCGFTK3AB>DW4J7\93DhPH5OjBii<7m78KNkXIo@`bMAZ0>`j6cJa3R\ZWPMj:Hid?FhG[SL1AcIgO4XnoTFmi^0]XndI1TA4jloY5gN2DDhoKIV;V2oMM2co=Cn3JF:<41Km40CGECHh97BKKSIOKa0WH]JB5A>=:jCf5m0k4oBF>?hGJl[U2Lf_RA5=T;\UO6NRc:caZhdJ9l@QUoV8h8gNjLWVaIDe?AdXR9h8HJgBf3`oYlbM\ngb?h:JTU`TVJb1:BVCRkl^Q]4=\I\Xd_5m]\MWbWQT^P]4IjmkLeX4PfB5mZ[lU:oB1KL;N3n=[>T6KA7h]E_@aYU_N^L2gNf??GjBO0jHDDLdlc^Vhj1>OSZmg1V;SRf;lU\f=UHdb@goM1JHIlADoBUf2Ri1?ENO=CdN305L?fc?CZ59>MIM_UdIG=;[Z>Y=iVUdZDc=7U>7oY>[:M\i?ZfHUEFXhPI]k\dnA31QRF]OCocEhQ8_b:J3nI18F=b_LYXamo\jagYd>ARUQ5Hb:=18371o7o9_FERGdJNCm^iY=M38[dE^hLa281D@QM81:NY>LC?mSWmGdnA;>n6Y=Jn7BlYmNDaRC6BK]HfDGL\6_k;1>h4?OXjm6MZoS7eCY@\[_oVn\79fP0C`;YEDf[?Df75\Zf0XKkggC4iaM@P`]nh8>R4h4h9CmA_B3`j^8hN;nAGS[A^FP_5I1?eCEFB6ci[e>n3jmmjJH:JZ96YO>nZQ90DfT`PMGSJgAW6OC]f]VeiR8n6=J7_b4GjG33NK0HKWU`HQ3D32Mf]Pn3c20gdSkk2MAn]n>R@=cKAL6D8\CU5YoHO0eb\8HOT6kC0O3GLaVSXoF_Ch3?E]7E?\>OS7;^VZmLmlhIMXHMWn1UAZZ=A@d=Z\`GT_V\DQX`?U^8Z5GoIgVG6ldZ^4>KXoI[;1bkY>4nB[A=3:bWN2Ld:6oQB^77Uo5C^SH]@`W1cPgRYBG^o4_?f96lSFnKHWW\S7oVLE8VA`VZNZ^eOC^9S@]dYJF@^^NX0=Gf=ZgM:K?k4;U?m@QP3L3G9CbfG2^IJKiQoMg1WEjPQLPEA9KJcb;87d\4DSKV>D5TX^hkVZ9jhZ2@4cX[K=k2FC9T3_YmW7TMQMC4GfSMV5lRP1BWUTMXNbMFOc:bLIOQJ7DMbSG[LHk0Yb=BS[^DL7e=;3CF[b[]Fj]DXbH6fkCQ5]jJ5:L\BL0CGD3mQZe?VBUk7NLN?0CbB?4Z;hJTijiEP>mhl?ad72XJcgj\ARJ]<^K^Q4\ISQ_B1<5EE9?m\MQbKUE91l`L5K0O6o1Hd_^lR<2iOf>]JJG@nD@T_775dWF@`=\H4KX:o_f_i?9caL^d;bPK4gK1=ja]6I7n[hA8^lC2TgV6l>ARM@QQfgiZJcDlSoIZMMoe^MoKbfhUQWlKe8I5TgGO@X1\Fai82_OEV`c6YH<<\=bb`VoOD9XN`BK\oDBGeHd4E=Ijnk7]0MW=7T]dHoFkFL5O9oQ[nYGnUFn7LaQ9G\hUYkda\C@EfDZlJcP0eU2^\Y^J5T21k`4=INh\98Z29?K8C8S=NMaNmWfXUVFjOfVJENJQeYki9aiDYHoUWbRCND^_lJCE^4W3=iHTEl2h9Q1^T1O=nb1S\JRL_2ekbhWIckN19[]RXP8gFRK^AI_PBI@R7XRDNP1PPUlRmgQk@j[0k\QkD:Mk2e4RV^FXH:0ePJ2PZ=M@fmKXm9[FgC932anG^_XBgedUbXOeRe2`WS6J<<^5gJ=b@HUDcm:^8Lcj?2a?FNG6g?Z\f<;iXni\:`B58J2Toak:@LQUS>R3`8nLUcC;\OD?loMYJ[7Ud:P>HeQ2;NnF_?l:in5YIMSNPC8G;JgQ`i4Ci1^4;YPgL>LT;=g<[`4nN\4no65kicjQ893DFVNe;]YdUHD944<1occ>U]O0j;UfD_[\Vg15YE7K6NTeXP6YPgLgXe=W]g^@88P2JgcMm^XcHlECjcX_dLU3ZY2j_Qm>K?G3KQ6jKFX:ZcjbBYdG`;O`9_\h0o2kdDh7CX[;FDmJB82@LBH9cnjVBKgPgYFTOd63i5Rl0=:E@Fc2^4O2emO^TOeIFkiHX;KdRPfeMN1:dE7PaR?;0DADgb4n8E_M4lM1H6YK;kMKVfRnP4c\6GM=WbaR3fm]MPGkaXGa]7FngY5AmUH2Ub[G5A>U`ng[jaIRhmoXbc5GXV\[3=fbInF_gokToXBG4U`9Fdk8P>h^BM:1UO`ohiB4mFili>3eK0`N[[b@;^7\fGI7kY5U=FG[db4>_34WVb=OZIP\cK4HoI\6m>TZ;]R>TfEfQOT3b`APmP=j94TgO2lGlog^i6iKJTL5^j8Xe\]Q7nWgm<\O:@h8YOcBlNWYKXemG5QQe1f4JoXmO7NN;Yc\kTMYj@`3XNMWWAJ\hIDH;A8]O;e_nO:oEKPekgYW=K^XD7^Aa^K^e4nmlW[]3ZPi5<8dXEhJGLIONS]KOeikn6nBMEW0WR8_0K4H9:5M5`k<11>fXLfZC3lFU]4UFn]6Y3M9:oLE8904gYPhKd[4k\Iob3KPn8ZT;oY[GmPR5D2=G^lL0fR_SFaFIIVZ:dDI>n1jAHQQSC5^11:3LK3a63j?N_XVh6=c3KV>\lAF[PB5kB<0QQ[:YU?UBVS;eB`99jK^BgfL0Sj_S3?=NjgFbdF0BBP[g^T?jVi?@I`oDI;_YCdGNVa?N]Q4N11SVYi4SGSRj[m_c<2D7k>[1on\[c4Dl9hEbnj:JLIL`M@=IF=R_MFDeKV1KVNFB?NYZYdfWJhUC7IWbBVACgIgemRlU^:S=80jjL_2iL]1cc>lhaZS84_eV`o743[]ZL_=E_IkfS4o84M6jWR>Ue>9hj@28i9@IAE_QAaPRSL^hHiE3^JD<>GEM6^H@@3LOQU@0fM>cgFLhI^cGV9=60=MVl]0bVQLXcN6]G57dJif2fZgKjbXcX8XBi1fNO@Q_5W``W1\lOT@Gk?\<@AkF76`bci\bGS9==04n;;GT]lLnRN95@B0K]>UadZ`?JHTCg6XVk`_1F@R]]A]^dRB6J3WDUWT1Y6DV5[H^D^TZ91n=NjbSmN3`_J_9\Nf1H29hJ0HUL:P0F3=^=A\i7k>Wm_bYi;WJ`_i?K5]08m4L`0IV8ZBLo:cFD2da[o:=5EemQGcP[EGaM1@dDn2WA4HQF]?k>O4>KR1WgAL2o_Xm[o[0REAJa?D?S^gekI42Q7m=K=7Z148JRnln1L8W9RISAT\aH;\\>LoUQGYifB3C[XKKbaEGBXI]?2A@Mej3225l_V@O[;eYPSH6cVbM^o1LA6_YH2Uo>lQ^g]hIFH\BbMg?AYcZGJhA]O6g;`@e]RaiUC1<`eJO8`9::15NkI6:\U`AVRO>Lg?f5RQ83R=Y;6n1@YUJGTUmkC1Ta]28nHdXoRL9SfCbjOUg@eXER6KC^b?fBB8WWi_Q^oAljXcO24FPXM@1mCXnG;EjHPiQkZKMQb_4DP9Sd=JmH\`\K5V:`XaK;@c;C5o2@WG0`AGP=4NS1mgINGPdLo:LX;HgA??>=1VIBEMZU5HhP^lJa87h;bYlU[GBlQhnjae2fg00EfAncb]c74E1Ie[2PiW=SC7oNf=Wob>44HQ1P3^JgMRRa\Qif>_dX=C>H1X2jX<33kCmGM>:TT^`k8a5Zf?3De=4Ec]FW_=5:aD?W[T^nh;6T3XmSaOL:1S0ZBRd5lm^g5WLcL5;1;l8D@O:bHGc4PU`j7o9^hOo`QM:IOEk^9a@MW_RNIZi0\2cAJ[6Wfaob?7NPRE=XO@5OD5gSmLVcM^J`SaQ?f\P;8nXoHJ02OiaVO3g5UE:@e_PV8Z_A9if1X:XkM@a5mH>U;k6_BDfKJ2oa`hom:QPWiNi_VAik7c55RB]AQdG3Gn@J=0j;GQ2LP[3eLfIg;jWVVm3f:CElcilGR6cXd@IVME>fcON:9RRHFe87i>KZ21P42HfL8OQI80[B[7^Z_V]`BSCPXlLQ=K]Y7iKKMWHV0E?6[Qbh8F8Z7C>Cf2V^:l\^SHM\LJmhAA568jU7gmY=Oo[\^KPeTHN2Xo6UejgeMP9E`62kM5HAgC0F5IB1C87M66f8M?^M3o6g3md?5;8QJHRJU\0d3m2QHFD:YPYo3g8Go46e:5Z6191DP3k5@gn_P9hfPB2d>[JATnjoY=e5Sa>VWYFWkNfIjoMmX1Bi\^YAl]HZHTI>Yi;2D7UC?A99P>mOR:]O]@Da0:2jHPaQUgn6:A7Z=Z1jLIObWNk5jdYI^P7@CUiRBZUehRj>F?TEjfT>\Q0`[fkH[cD@cA97LHcH^a9E5B5nO2aW_h[DeCOjOCb@_a]H8OY4mcjA_EeJQCi?YEX:B2CD`aBYofj8F[H4Pe[M[9_9eIIDaU^JUH[U1cEFKVG@`B`K\E99R:?l=EHBG5_DJh12W1X_c4gDJh:on6a;89F`N2:T0^o\I?2n1Nd>5KVI8WDdagQORR3^MhE]iQ630k@NeNb[Al`\7kJ[Bk6fUKdaN;QId>NodfbH]h3=IZEm5<[0;_22KMM[Ccdn9;MOdTOUXQVWaaN99QZ36XJ8M]2OiR@X;V>C]=gcW5Tf^Cnh<34kJ0>89;CDkiSgj6>bNeTJbY\A0`e:@4>UJ[8kEn9;55\TI=Z^iJPL^M5=j<[OZ`EHBA@ec2jX]ecZ=M`ZhJiZnCFb2>j[EH[nm2FECl9MbVU=_=dI;BWN\PV72j9DYZP>>olUd3>HA8@WULNAL:R1?VHFoFRGkb]U9L9bVFOP1UF_R>]DGa9G;?E8913m0iUMAJKFo93Jg>M[15mIaa0l1H8PMfS6Y9_R?J3]28IUVU87WZD[oYR7:c13]XkZnO9oB;KGM3>Sb:OZ32[@`oa`A37WlLn^ScokFjEP0[]Jjm6?ci:k=nULZ5;5_QFo]nK1bh8HGeYVj<6_OMahD[Z0dlIOET5F]NVIjnZ\MCXPBJaZ5ZPcETFGid0HRbBk4k]?oDTIFYj_8J?QVOSJSBM^fF`eKC0JD=EY82]MlAf898l==dUn9mI_W[Sd2m@cGTA3RCjLJTIjHO9B2jIkTSSngL>6BgJGi?^4CjnZoKG8Z2gQU8Pl@gm?P;?274g;>@N9UFm9>g_i5YPXFZCjneF\WEUlI[RUH2^V^V^RDG3JPPna_=mQ2BFj]@;37Q75d:Y_LIm]LZEjQYPI8eKEeVKU5YIP8ZTPBaV6okgakZ5lc=nUU6X^MBW@2`6jKE\df57lToiGXb_92g0I_BVTmcEQf@jf;9YRKUeNonej>h^BR]O6j^0@_kRAh1ciJi`fS1JgGSAVi]j^>jSigE>aMH1TH5Ue5n?RbmZB1=3LaQi81d8[O>45GZ`lFG3Jda;7UiFEj@DJRUID1lY^5IV>[cecnc=Q:1CbYS77I_Me_ac3o0n1I@dg=kDh@O`aM;@@J6UogQ4O`@:f=`ca6bcJ;k=@O=7>K90En]>?K;DhUQnGMS]Ek@[]?`hhc[TDJ3_F[SO;73Le]Wh^Gd4GZ:[^2cDN9KV?7SAg24k9RN?0UW]L5ZS\OQMM;F9h2M>=3Q6O?[RC1g[[>E9m@[o[aVb@4]A=k6\g3amdIK1]CjCW@A8;UJeFS35lWTZMXm@VA8V8BHZib;^Il>`cC4Fh]hf>9OmCVDNJDW_P>ZTo>C]JLPf<74iJOjj9b[_3n80>db2L`o2f?[[42AZA>PEP\C:MhgWjG2i[h[J6TS98SK6f6UB91=[e2L5JV[JZ5m<@V5Y=N_f2>aTWE6L_04[JB9Q@_gXahNdI;RD@il7h?Qn8m^NE>a3SF:ob6o=09[HBE>m2>PCE=`ghY6@c>PC@5k1^W]DDUjaMR7C5DHAj50SIGWNPjljDgLfGefFf:2:O@n1hd>?Z\Ue:BW6e53ShQ\N2f1aHJ0jo4cLTK]]eLI4R\ggg>J[gk\M]WD?BU8IO7A9PDV^9gYmhHg8eD_Qb0I9YmifKT]Eb8PYFPU2ehMX6>ii@1>hMZBNVmTALiC2?1C2Oii5C>TSo:d:Kg62Hcl5mZlU2<5QP8j^:C@`AS2R4LQP8eE7>e5LfFQiAlH[cn6bmB>55=biPoY?gMRO@N:1U5_^k\eN>XLe`?JQ^8J=IHLV>8SN0BCIP<5;A?1>fN7S4foeXNU1P?X]O`YZkI@Ooj\c7oodkc14PSYPeDch5I]SFlRHPM6o7D?oLk1QleG<>m[Rc>CN=HN^oYdB^KT^93j;`O>YfFZ;?4AAoAThgD]Qm[2BMA1bP65XDlo[gJPZl9WlVn9WCm[X^Jj_DU5k_8`S4lE[enKS93RB@>4:_bbUd0REfo=KDRn0R6\BljU07jIHYA>bTZaeUaUAoM2mP1j_2i7T^7TA[jjFQ4ZRKBgb:O4cZRTSUjloTBkdin6Wh6YP\PeJh3[[hQJHIZ1@EmHS8I^ld9N3]kWohcjCCIYC?lAJ@Sd3eeTP85L3WADUJ;53H05bJ\I\bj2O3PO;`df82GJXGbKk4]kaRa09^D[8[PIM`_Kd6SQnM75WZ3jWiB;`6o@o0TDT12G7Z3R\GVkdhJeB5CQGjY3mR6NIOVC5gBiFM`EXILkYIiC0NIB;PQ`e2a:BJb;HnZ1R?JYH;Y2CQ4biJc13_iLbQP=j;M1nL9o>3Uja^E@Gnbi_mmA_WLA:k^L3Pm]Ug486Q2Th3VXHd^1QlBOUKbd184_Q5GbPfB8>A:?k05U_m?c2KH;Y8dNnoo:Sl^fiUN9HL0hfKXnb7W9hc:`_X`@A@YVn02BkdU8o9ZXglC^a\=JcfMRLamd9@m@@6KCeZ=KHJ[J00=;F64AK3n`oaJ26`0mne?[BE5KfW<\TTbn=7ScNYF;_1MInbYg]h;P^bk0f\YEZ5PR;QDXIKlI;CAE`Xg:7ed7jn5jen?JiYm_@GM\hniR4iHNRL1@cK7W]AbV[FB?ibD;E9YQ3>oULXE[O`>9:D=5\g0kHNVlI8OTFEMS0I;R\HCjX=]c>YZDAche?4;;LjXi@XPXgLoJI0[`TPHH@A?]l;43Q<>mCIRTaA5_R\YjX?5I?=[85kDALb;UaTI8R@HBgB[dU1Wb@Hn1I>EQhiDR15WObEcfL3VGW;`X:BMN6G@CkDUaVH;YiLQ7iJ>icU4h\N][j1Ad>eQomSiCl:`aZa`Z^e3R8GUWl`>VRRQDMjgd3BRRhUBM1j]5k?9oC71KAT9NMXVFad^UZhFT[ZF?5T7l25mKIfS`N?G@F8gF7;eZJI4llL[o06g`7cE>?7Tf@eB4^gI5XSE`1?ceh31RJ=iP01ESeF[HW3V0d>:edh]lF5P@01?g;UbLg7[jR>ZAKnZ5gV8W2ZjNI0P=QmRC56cF3dB@o_g1YXTHU;[Wn>lh0SbE9cL7KM8AaZm`g@08CkNeWghhoP]QmWj<^fXW=iDmIhjVbDYf9GUNcAnY:h?cOi_jEf`hc0d`eW@2@7o[Cj3eGTA2PPMmYCLKMD;YVj@MQRdn\;ej<>`?ni0^AaP7on9TbkJIi@G;1fZleZPQb6mi0^Nd:LdVV15>9kBPWXeE?ZHVAQmn5Cbk4BcQ5`ehJW4UK>M_8==DYIF@KhSPV[e5EM90eUiPaARnEhfihjm^XkjUbcl=X\07\R`3gJ^^8YMnKFSf^0Fa104T`c]Rk0mk9GHPnMkjj1Mfi=lB3IkW9e5bGjo>^dNL;R\4eZZQ@G;`Z_YWOSG4lb?^4fm\8L0Z\oSg5@0`ib>;FK7S=YgLag6cQjb>7IP[@b[A?J48=@gT3?HB5Go\Ygmj51g]IhKPR65g9C6DfhSKNRgPX`cV]VZB`g05]5d9bDh\b17kaX8;dVZ3[eolMUWE_:e8V[kWJd0i_fZKX\bYNb\88D1O=3Q1k6JQX?lCIh1Lj;bKZl^TT6dl599n`D_5XiE4NZ5KoFK5RngnCK8a]^llM=6f[iCE[T9W]3FemZ]GRijYjd?\VDm4B4hOiPRnjZDI17f;5KbWifc=iMBlN=GTGG>@J_\m?X16H68749N@=7N5E>P`^Xli>>HdBbDlbaNSfn9jR;Fj@R6ac8hU4=IJjN]ZNFd;0B4^TYK6iW]TRT]:Z]4f;0K?PL10;4[>IoED0fcOiPboMM6EK`4L:be8G1FAm;_]=OeDNG0jkDX7YKj>2<[MhB>_CWdbd[h_lKD2LJTT[0ElXEFHd?gFP6ZAV=2Ve@P:`cEST@[^e_gGVQMkESH=D_Q0OO:g9RM8obO^[kai25=Nd]ODJLMJDi\I;cogWKm09U4iA9<3JZB[19cX@57N>:@9LI<9DgHUgX4k4][\i38>:;27lTL`RF4fOUBj]S1@KQ8FNWm@Ah1ZP2Cc:ESM8:6Xl7DUDg5eN`dP72?VWTd4cLX2>l1W;?IjYa7GYZ4QC=0c]C1YHjIf5OVG8dkFQ<;h]ASJmCBlPIbg?6X_Pn=?04oLXUeWYbfTo8F\^:VjS7WPckH:RB1eK_Ui[?TjCeOac4_ja^o:Z]HNPCN=hZME6U`oNjgcZ[H2^Uc:_:k>Bl>6eRLR5a2n_iWXZQk_^oDiLHMd<4oE8L2>:]S0m[UYYJ7SZ04WG^SV]Q39\h:6dUC11j\IQ?Flh18[>D_I42I0FCfEkem]1YOjInU^3?OFhmZU[>J<:gNcL9XFh=W=iOB0@LcJAAbM4d5YS@nV8ZC[:YiRhiW\V]8eGlXDmg>NS5W9YmNO;]kEgE>MWI:on]jg3m7TkF]LQ56UK1:@BUVSKBN_iI0doZ1WGc\B0lTFnef;jTG9C6<6nWo7IG79ACNTWK7QEImkdR@FJnXhD:b5`7m<=;[Uk8gJAOb[ZgV=:PjN_S`df7XG86j0YWe[90\iDDeSe[E5eSPaI::e=F\KOeT_>m>2Jb8akLn=:0?mkeM6_2bZP0EY;0f\C=aL6;AD\52PHbl0`4UZSoV[mK]@:_=GVZj9cg\mF7jn>@0on^WEZgLEc9J1@6P8dULO7\:Yh]ogg]HALG2JmcGX=6>YidL:5GR\c[5RRR6T\8JkB@Na1[hN]N9R2ilh4iDZMR[CV]22CAfCl7GTghH=6BjCO\EIMQgf]6OBK1]aoR\mVLIOnb6haMFdbJ2cbCh]fBf][J5DDkoiA_W8_=8:6kSnW=JoPDD`1Ioi5iUG`A;DV7n?V1RP0Ofn?SGhZfPHLQXid6=MZE:5MmWECI]Q9\O9e7bCa[:QS3KQa`P7l5b^^a?X1MGjV@JiD1`YVc@``d4=WJo^0<;S:Z@UkPFLmXJS][RN]8d_Xe9_FmFhgjc6i[>8A^gdKdI4c None:
+ super().__init__(parent)
+ self.folders = folders
+ self.output_root = output_root
+
+ def run(self) -> None:
+ shots: list[Shot] = []
+ try:
+ for folder in self.folders:
+ self.log_message.emit(f"Scanning: {folder}")
+ found = scan_folder(folder, self.output_root, self.log_message.emit)
+ shots.extend(found)
+ except Exception as exc:
+ self.log_message.emit(f"ERROR during scan: {exc}")
+ finally:
+ self.log_message.emit(f"Scan complete — {len(shots)} sequence(s) found.")
+ self.scan_complete.emit(shots)
+
+
+# ──────────────────────────────────────────────────────────────────────────────
+# Core scan logic (Qt-free, testable standalone)
+# ──────────────────────────────────────────────────────────────────────────────
+
+def scan_folder(
+ root: str,
+ output_root: str,
+ log: Optional[Callable[[str], None]] = None,
+) -> list[Shot]:
+ """Recursively scan *root* for EXR sequences.
+
+ Parameters
+ ----------
+ root:
+ Top-level directory to walk.
+ output_root:
+ Base path used to derive output folder/movie/exr paths on each Shot.
+ log:
+ Optional callable that receives progress strings (e.g. ``print``).
+
+ Returns
+ -------
+ list[Shot]
+ One Shot per discovered sequence, sorted by basename.
+ """
+
+ def _log(msg: str) -> None:
+ if log:
+ log(msg)
+
+ # Collect files: dir → basename → [(frame_int, frame_str)]
+ dir_seqs: dict[str, dict[str, list[tuple[int, str]]]] = defaultdict(
+ lambda: defaultdict(list)
+ )
+
+ for dirpath, _dirs, files in os.walk(root):
+ for fname in files:
+ m = SEQ_FILE_RE.match(fname)
+ if not m:
+ continue
+ basename, frame_str = m.group(1), m.group(2)
+ dir_seqs[dirpath][basename].append((int(frame_str), frame_str))
+
+ shots: list[Shot] = []
+
+ for dirpath in sorted(dir_seqs):
+ for basename in sorted(dir_seqs[dirpath]):
+ parsed = parse_basename(basename)
+ if parsed is None:
+ _log(f" Skipping (unrecognised name): {basename}")
+ continue
+
+ frame_list = dir_seqs[dirpath][basename]
+ frames = [f for f, _ in frame_list]
+ # Detect padding length from the first filename encountered
+ frame_padding = len(frame_list[0][1])
+
+ _log(
+ f" Found: {basename} "
+ f"({len(frames)} frames, padding={frame_padding})"
+ )
+
+ shot = build_shot(
+ basename=basename,
+ source_dir=dirpath,
+ frames=frames,
+ output_root=output_root,
+ parsed=parsed,
+ frame_padding=frame_padding,
+ )
+ shots.append(shot)
+
+ return shots