From c4b49814fb90051b8f15dd7587b7aa1753c98ae1 Mon Sep 17 00:00:00 2001 From: Nulo Date: Tue, 2 Jan 2024 00:21:21 -0300 Subject: [PATCH] RIP WARC --- bun.lockb | Bin 223272 -> 114496 bytes readme.md | 16 +- scraper/Containerfile | 15 - scraper/auto.ts | 128 +--- scraper/cli.ts | 12 +- scraper/package.json | 2 +- scraper/scrap.ts | 84 +-- scraper/warc.ts | 157 ----- warcificator/Cargo.lock | 1373 -------------------------------------- warcificator/Cargo.toml | 17 - warcificator/src/main.rs | 199 ------ 11 files changed, 53 insertions(+), 1950 deletions(-) delete mode 100644 scraper/warc.ts delete mode 100644 warcificator/Cargo.lock delete mode 100644 warcificator/Cargo.toml delete mode 100644 warcificator/src/main.rs diff --git a/bun.lockb b/bun.lockb index 280e6488b71cadd6d6bb643b3b05bbfac0a2651a..84273621e28f57e338cdfa65c8a7c95fda1945d8 100755 GIT binary patch delta 23530 zcmeHv30PIt+W+1g4xFPM6cj-@PAG^2$Rr0DjyR*JWo6jlfN+GPOadyRcn)Q$4Gt}J zsi|pcYG#>3Dh{dL%1X_#%<-C8T56VMMxp=TyZ2rk@>;k1efQq)`9Dwl;dkEk{?@yu z_g!o4%|5VJ9W?K{dre+)npS-2R-of{Jgv~hr_n+q`ZR>kucG>o?n>QF9 zy>6#0(Pffn4{qkPduf^^6&Beu9T{Z>Wd&Jkeqs2SvG%cc=_=VulIt9#8L}`uFQX9Y z{EYkp2TXGv`J?Sw1$kq0CKTq_^QBITB-MqTJ-@_J;;&VV2DQ~Rxcs+VXBeWNf80*N*lBQTB36#?{ z1_^S_5Xgp*X7)cHA(RIf|V&xb^Vu19pe z2V^73DY>GMAVUiz`QE4-eBVTC;0z>nY#$_5kYyh+HX9?&E2i;E(rS?8*rmG6%*n_d z4W8?|3z9nac5BUpbwe~ytb!gui|92FuyHjC)m&N^k|xI;uKJI7%1JK#bFTXHp322& z$YYO&Yo1vGNpr}dZ33#-Xl{-5g8#{NnA`U7k@>|KxLOc}RgaVu=Q?Oswd|x#vf`4W z{IPkM>d+} z-2t9PcD*OIH^}l{n%yNxDknm8B1&r@zPC2Je}JTh=Ae9A$YMz9NH!$xBT0}AY5g}x zf<|x~70?JSLehx0K+;ItrD<~_0yY^ zholB}LK6QP>>EIuQ6H^>(Wr;!P#V>T8;z^IUU3yFBEt=kG?F2ZzL55DxE~j*dxN?q zKlymlq|^cH_lC!v|E6~j=kAG5oOQIHJ@?qEv)8}+Zp*c(mD8`-Lo>p9$5_K&ef6!# z8;<|d?fHhg>d$yWiapol!}peN{M)fjpUzC(uq7x(Zjt=_j2_ipcUFfi z`f}?{#~FF#azMl*tKAz zGD%`(c{bA;Oi!#+myuP3SxrAdOMvFZ`eN&^+00Xr3OL=D~J{T1|bSVduE=`| z8m7HVVO>M4#t(Ikk9ks#q>h_>JS8aw`5vnE0BF=LNv+ofO{x(DXoMGaLMbq?s$iQk*^4E#vMGnXSQ*4bZ&nHMo;Ry%Wixr=@rDMi)~9qc zva;4TiKmh~W-O6eT!2O3}BQv?RRq0=sm9?>%rh>#A#_-`*WpiCt)yAg$ zQkNx!*_4j=u(B|l=@~5TZfZG->3(PfpdqI4Zd*+L9%^wKbe@@&wY8ZxgCr9SEX-;! zV2g@po<+u*!BeP_JgTpyrX#sJEWfj$skB zR2rJ$3#10{is^EUI`5+EvxE*dQ)zu|b|_571bVAJtL$Ji-U6A5D%}3+<;xPnZOS5F zRt9m-msN(xv1_@hO1K|O$g?R&{a7VtaZ{{VY=znYlras|SiB1X6JtY`kZ&`lV4rh` zKXR4H2!i^H+1kabyxx#i<=YHrKqj!{4v9*HKPxM+nTm1apgAO~lVq(ws{;8gNSbDd z!Gl&)`$m!!p_+8HS(S$yvC2Z5X*$SuDoHWe0F8ns)5ucV{{doH|`_k5>J}^ zrvA{V14eZi(;Bm?Vw-6XNOB40m(6Odf=27L#`&iBCR#YKN-@>uG+~u-Hp4uNB=uxF z;t~xfk?O6cf^qBUqozh9MY&yMP5&9XW|M;3Lr+$26*&i>_gBjVVV~Blvyi%1yb)RtE)yzE88nr*fFFu?i5mLeWsSJ zG>3Y!uKld02cUI;N8tUQR+AGNMMqtDrmebWQum$fdO7T1Ay!jJYt2&KDwScaS=m^d z=_8OSD2@%V&}t0A)8=nxx+xP(AGP}35mseq2rCX zw;2wD?8%bHCmI59NA0bqh9cERO|3*q%e`E~bqW)9laSJKcO#{hsDlTD{%YBDq%>|R zQunIdw>7y*nAT{mG)Zp9%1XO8816fK|B?&MM1o#@1MJcmQ=zSLNXdmN407nu83Q z)rb?83q??}DeF)Ps&i9)ny6t){TsX}P_Dsfs(Z$XPip0uGs8;e*@t#nIv+C|iayM4C z&}L!?i@xV!MZMFFRV}m`Lc2>+GOJ#gXv##Yrb~t`&;}B3Fu_;dDW&x5L8CXE0+Ge4 zQpDKs-VFm+U}vG_GVR!@p#djB`mR-wqTaQ z?RuV1DysyUnJP(m+|*~;C(tr$w9b8MHf}r^jOoKFU$iNeeOT3tHiLg(Ny=c!OA?iF zeOcL3o8es$c6I98Fhfw1s+?>!OocXxc;$yQR<_J$=-CgysSsgUj?@rVzBJJw_b0cY zHpBf$rK_pcNEN85K!kgcn#w~;<4z$pOyv^q#jod-GF2i)d!M>>8mgdWv+|dcJh4); z)du$>m8qtVV_p=i#nZ4jGF0wUq!61~Nk;gS7KpY5=R>2lrq$|)37^i&mnE7UNYSLw ztlojCf^ewq-9k!hZy18Cy3nu-Db?KMjl~DA=#@SI4Q|!7 z#n56^jduUj&?uS)CP#O~s9!dRe3!j=)AbnKrkEH=N4Rkw_o>~AGCVg;y!*ih(KL|VhDJ^Zd-B&j19zFHrGsWylh zsTWDAAHh+t2PF34wmK%F5D7_Ur?&-krUnoq^{Oq2$L^zEwIz*c7_lsQdw`Rg&ms-i zA4zJ{4v-wFORP`z`ZJQsVXIUxlB7E%X_T56rSZ_T@#jHOP$vRpI7ye~kaUrxVYmRw zuK?&GN&4fY;37$JnhGfFxz_@mpv&8>H8mPfJXSf+WkL}di$y& zjr;?E3Vx^;BuV@}T^`W++OiS2FLeH2mCk>)z`xTT19eIl&~qB`m%98)9|=j~FY0=2 zNt5szkN~tJBVAImy{?m_NgDx4R7ZS}C!=&3qsorB;Uj?`DGnc0u}#;zKvIFOkTh$1 zL3%Lro&YCl14)B?5E4JqAYC5}=?VQYNGd&4m%|~wp=U#SLFVavfzFT9^-@TxccQMB z>(U8H?M{*5GfGScfgkBC;4&nQ>_+Aj$Q0AgMwho%hvcL!A$V zqbIAVZ)#AgRGzNUEp=k~%h4m-Nz#^zo2nzX*~> z^b#a>d?jQZ$TuOW{!Nf!kf$N317ASm$0>b@Pr8Jp^ndR;0P(-eg8=nGeK4Srv;t_P ztpU1f%m4Lr0J&Cu5MVpD1^jjI|LfkbPOn@eiK_ z5r4qU`ws=-E%AjzL0kk;O@v9}eTRXV|FM~`9R{MV#H)x%J!s}bhJ!Fm{MF$gZh|mp zfT$<&M>0UHI%MWMi13wooe>}gA2##65g-~!ypjmx5i@U^DW}Q)?6ZC8Y|9ZdOWvO* z2e9e;(^<|@GrIz_9fvmLP@3F|tv-~_rX4pk^Wii(ggtyXoyC7v@VWuPL>>{+h zBWZG5wiVj^6K2-*Xqw!fIgX~Y)RShmA6htTd@P;agjRkmP437(fVS$CnT3CnCP%Re zpQN+Fr_Jm%v>4X*({wqORp7G|`wX9PEb4f=Y-Q8&8PCq)voq`bS-PCSX5%xFUBYJ) z>v|$xPG$@6X=C5vvkU8UGF?t#%kbHiRqRVwx=H-|X!#+fyTo6Lksp$Ku*Nsi<(_QJ zjdZ0Kf&)(JE%EzfAyW|>l6@qubb{=Q(2z`%_mW=I_QKLighD zSF9AnugrX`6~sV^?*XCQFYzYvkPk?_h~$HqK_mxBJh(IDLlQ3|nJ)3eBnL~pT>|98 z5`UcJBN9JB@==LLCqh0Z@ux`+k@)8%he|vl333?P35Ohxc1UJm>VlU?F!^G-oXH-> zXBK-CpLS-tlrE2C8Tia*Tk)C0e7{bY9n68xQEWFpN3+J?q|3Q%3_kPN2l&iqEib3b z1#AL73)vxjj$v)Dq{~ID0-wd~Gklh?sH^GnST-G>b zK8L80oB?lkhnxv-lAML8k(`aF^?-aHQ6tF^HIj1>wVsf35jB$Y5H*qEdnH?NEuCK^y&Sr-8Y9Yr#e6R?;dU@g zRBte+iCK$LjRbR(nCC`Ao17>j!m`xZR zFgh(2Uh23Fr{WN=3Fpu zV}0g=3G)H7gP7fjbRL-F#N_3Hc?Yp3W?DTkP4mILi)iPAiLVc4KQZqk-UVPT5>s9P z<^%YLnEAe7!VAHC1pgF*N%aGBnwb6Y&loT_iFs}en2+HfVpcT(lUxMm5d2dFW^h9= zSBN$D6#gjzlhX)HH8G#TKV!iJ27p;R7R*WbhnT&@ z3>gRJH2gCTOlcq(^LQ|4;h*tf!Wx6wLCiV$rxeU_V)9DCoQHpinbrhM(+OZMz&{hf z#0P=dPs~^FPZ^kt#FUqTxdi_ZGv5Lxd?J`{;Gcpw~d= z&106x-DTpGJzkreO_hf#%I7|O@^txzN(TG!c1v*6a|Jgfy^i*`sgi3`gU$I%G(FGF4cHeG1R1=&}>GQ7G@OTuiZv;!s{8bIiiS4`S91!ou|6#-8rIcZm~-4 zA@ilv<>CC-8FCm5EqwS$k9aNPU;U(tj{Psn|Eul&JMBBjbyw+sA^sY|8PQlta^AYF zUGzKMRRD2R-<8(Z>GjcfMBw@sARBsd^*ulry;~)YUP95!C%VX)ekzN3Zb40(9K~$d2BEy${g!6F?ljdZX9jly?)L z*WUEf>p6ff9~jB>=Xb}w$sB)Dc#q7#4N+S1z@|!|lln+qqApOAR1H=66+q*q@zHpw z`_x_P9(9MBr{;bJs(@dBUx8}i7H}J&{>gv>cmSS&0if7WXYj{v_$yc>>Hu|tdjK;) zeXa-82YdlPpaIYj@CO^Hz=;0iDrXa_{_@}^3F`eh&^>69@6KqwHKf- zo7Mqu0_%Ydz(!yb@D{Kc*aB`7a#@b3UmXy13iEM8sGg$TmU`-J^<(y z*lYaFmI!18k}iP0C>#kq0t^Q-fK1>qU?|WF=mUHS(05Gxfmy)Qz%#%+fCKY^1;8+% zFVGKo4mb~|76YRJdc94rx_8rT-!3B(P*%a{Lx8@p`WQF}90CplM}VWiG2j#6Q{Xu8 z8E^tP37i5>180D;M@7!~oF%bu1F-1jGSWfM#tM zAO&~{=mwCpmjEun2}}mcfl0s!AOjczJVLp>kmwFjr83Y1=n13&G);R0sX$+VX8!=- zL0}L-Qeb4m<=M}gtM zFrYaw6bJ^W^CZc|WdMzK0#FK!2gU(offAq?2r0tH7@!a+0P=x6AQu=7i~<}yIZO$1 zPDJtvpaOUtmb3ZUB}h4lu+kH8PW_rQ0+ zHQ-y|DsU0F0$c{Z0lo&l1Wo}LfG=pOoJZnw;CBqH?+i5l6c480j?A$)1)X=~U-efL_k2-lJ(Y6G6QvSJGq@-k?I40O58jEILJD zqsj@QGqpoWWoez)4hM0f)2Ar@6zkf(67xXx)@@w7;BV8l8=z2J2dF#^Oyr3H)eg-m zioY;y2B=fN0<~xJN$3PI7`i|F^8vyCG@^6BpB)vA=yyi*yMv+nsoYn!%BtZ; z`@e|?kre0uNsMcc{08dz=cC8|`=1)U*byn5s{k4ph4GFMT54k09GMotNWY@u%F2|v zcW0$-bR9hMedyJ8M_OdX4@P-tR77M%r1t1cIWOw}Hin!|5it=l^uWw-O;7@rP>BbY zDgBfLiH|H(1~k(CojpeXM>jj$^gCEXl1)6pW{@bEw3BYhj^DEyYJ|; zb=#k7DBF@z2d?)F+?J#S#+`+Q584jCFW`sjoyyRLayvC24@r92KJ}#M?+bl%43$+! zEg8J{vnXo`@Y4P})ivy~ncgoS3?U161y=_zzKd$_3JY@3HuDQ@)AxSf-CcWM;?0M{LW%X}Wj46Kw>N*C^g-TyuT2@L*u8mV7x+n>A7E*9{lN05 zhjLIuWJDazscqhTGAyX%dXn)*{w0-|Y}ESSMqb{lY?JMKl!%ImrAhIOk;kUMk{fvr z$;(E*CMOQ;S-8wXPqmqnaX@X-~+;I5%>$H5{7b)pwOb$M=A z)HT`2my#TP4?hYSCk`Okciv)s&?C)PuM;K2Q3Tt5UE|v&c6qj17uE@$*3CSr8`i*b zGk>}p>S|Sw?}W67GXz}YzB!uSH||$O)|Ztu+n3+d9nlo03786!-urss!flE?xl=@R z9F_=OcVClui+eQ(WfNdg7xA7Mx@^+)B?BuJ8IvixGaM%V+k4xYMkh-*E-yh(v6>@d ztoZ+Ip5#EZxF3JWfgUdP(`M5rKArRZ{L}itva{y%)qZ?AER^+r{J2BuXW64$9_npd zzPelUjfxx@(U}I1^96XyD2(2x0iQ7nQ4uE}qz^pWf5`VAoO65db_2d@6c%itKmYq^ zC6JFBtu#?u`}2)?N@TOxIB_0=bozyuyu!@Ga2I(2mtMef!C!OA*RRAr^`3F&MLh&q zf1~_)!(8Qna>1W}k&Et%!x8r1I^K52%(u3}k~RQX<^=G5dFZA%PQl~V_eVre$r+_u zMAJ^=4B#%Z_{aWWLaG7R`n*sKB<^?mh3<>P7(Tvk{oABY<9eVKOlg|by94=>e1xLB zG2fC8_rZ-`1#r0TM&7JIX~O4?#K-*wN(Y;(i54kw=E0dWZ!caGy`!@y;t++PM@iyT zguUMP@m?46_PBGtZ^D=K#*7i?CoTwmv8D%Zn z;SBhn>3|-Wmb^aheYeFULA*sOY8S^jIJPFOiuKC-(rw`iQeUvRPChZRSJb={yWKf+ zf_OfaT?vaun9FN=IffK}Ar6r^w5)#9zlB}8*PU}Th;K((i#T>7clb-UKbgI? ztJ~sM5WhyXi-Rh@npg7uvMx8axh=#|7SlXm%NgdIQ0mUHTDYwb%8J7;c3+siszE^S zpWGJWc#OR_T+JsfAH>`_V=VkxlpQq%cUmkPS6sh+Z!LR%W0~7RoKzwHgIkfKwY!|8 zor= zZf{!hOQ3%~EcJ~?9BA>y<;o_zT2voGj=n3OX~J!VC@ap`xZifLy``z|O101N5z&#- zU1yJ)V+rEVqO3)n+Y#Aq;jqnK^%Qs69zlE;)h>?u*dtx-9ePPgaa-JV_NcYHg1FBZ zloe-UytI1qsH?`1!|t+oojq#V9YOptl(mQ>N!s~^#mLW`U*;}*F^JEi+QlIzBO3i` zs@J^X4Y$QzXOCKYYYRU^WyQfLEb(%yQO_;JcjQ=;s>NMrkD4>Y!aEe9XX3CGqpz*~ z7J1G-ciAcUnv5*OnH`U9eYW^Wptm1lhHZ+rkR{=KP7&@|IJHB4CYX3Rd;c`QZ-TY^ zOjJCcB|2(PD{CLk%g7nX&#GnBJ7joAo-zg7PijX#{8{Y94P8pCGNdEE;lxD3!`);T znil6C>{&m5_A6maK3C)z?I}w7s3ULjGKyd5$oG+@I4L3Vi)MfGm~!@GvW$(VJFPi# zUIlz4&Tg<(cdplc(F+IN2I6#w__v#04a?-)-8n-e`2du)Xa_?`uI~~T9!xT{J)&B~ z#iR0-k$llAbmKipSSnW{c|LW^JBlBqR>@1)I9(l^wdtI@EAlCK-QrM+L(b&apLslX zoV(7f92=bBR9@#UruxD;J~qQs@?OOva4s=eup}=DEgQ zQ}bw^yBd~B(flfvyf2#DmP2Mo^QFWWNAsj7P=h#;<8YrxUo?k5{f&rHCuv7CFNB41 zGMcwo2TO4#NYKu01ACn6I!{=}Nj@=rC)Fj65y@_K^6}Yi&e8J=-T0!ck~M~3rB(;V z@Ovoo!(wQux`aK-SXSE0|3;gg?(To=O&N#7g8m(GOzB8DHB3RxY)uT6*4XO7|* z%j-W0y?HD@vjQ?ImfN0&>=DaT)<9;(@?CGDXBBv;2}UgDl`AhNe%iIa-m~Z!>E&2H z{1sU4iRH8ALmrRie@BfLaY)Rl@W!bJPIOuAE>RuJ@0$iopH4jDDae+cc3< z?tI2>g^X5i#qlN6AV*sH$f@9U57&%Rj7p3~vkz4K;`!?f(4y9ZexjZ~Xj%7{ zMVx4J-D?b+Wz0ArA|v`1UE|5Aoq7KBT7CUfHK;MrdK+yKr{bKR;P=hDuLa^!N}UDR z5ybe#_(XICe>;&cU8MLo$G

BXkZ|oGCrsw)7#jlIRHh#vqLEl==j>^hj2}$#7+5 zpI^Ij#TxC`FFefSEsH*x^k(QkscX$6H8Ns8iuotzo9OY^vAof9h@5C#%vZf?%O7_8 zH#7A?+q@a>iY(&9pZCKn&+V*uZ|PkFq;^p>eV5UQUh1oXPnn5lTwy0N^HTV_rIb1}^L-hA>(l*XRDWG?P<1Beto z(Mjcp-hAImr8mDlS22jpKhZNWPw(6}g=_B`3%6&*ZKT%R*u}Bv1&>}L_-9HTA2 ze@hc3#WWG;H0>F>{EdC#TbsILB0Qiw*D?}oIsjYq`7+l_6FR0B{l>DkQ?(fzsAxNs z*af3Sr!C?rs7?hzlcSFH)9&(dc(+rt@c((|?)00sSa8dvRZ`1aYQKKFl0-kmz4;%e zxp0wifY7zYS95Q({GsdAhV{KeR3L(WXT|?azoT5-?@w=WDAv8NtZJEYBKmFj#Mk@q z2T`omirRUxn(w+i{>hO3e2i%=)e2Iy(taS1Sc}z|Hjv-K_7^A4-KukNZ=7kDy{r4l zNu2Bz8nnU{k(rjM=BSU8Zw%!9mT4{@b7R^yewO4ZPcqz4HMciETXY0)CyrD7r zelPfUM^!}gzZXR@620X=*iUQqNqrCzYeCFJF$2YV*7uPA%e~`wCWz(tf5rXJZv?{O z|Nl*$-#()1`+)e3E?Uu-zUAMvz&mVE`i0!}TLF4Vk=A8uUyEJC*JACnJ(}=DH8v3mq;w#0jU>A|E_WZn7{m)l8U#! z+BN>(qO{`sGP;-2-yz~!3Xj_C9>IL5-J@OIi#mIJhZdF1YwaElsbTr literal 223272 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 /etc/periodic/daily/scraper \ && chmod +x /etc/periodic/daily/scraper COPY --from=builder /tmp/cli.build.js /bin/scraper -COPY --from=warcificator-builder /usr/local/cargo/bin/warcificator /bin/ COPY --from=builder /usr/src/app/db-datos/drizzle /bin/drizzle COPY --from=builder /usr/src/app/data /listas WORKDIR /app diff --git a/scraper/auto.ts b/scraper/auto.ts index 582cfd1..b4bd8d5 100644 --- a/scraper/auto.ts +++ b/scraper/auto.ts @@ -1,14 +1,10 @@ -import { mkdtemp, access, writeFile } from "node:fs/promises"; +import { mkdtemp, writeFile } from "node:fs/promises"; import { tmpdir } from "node:os"; -import { join, resolve } from "node:path"; -import { spawn } from "node:child_process"; +import { join } from "node:path"; import { Supermercado, hosts } from "db-datos/supermercado.js"; import PQueue from "p-queue"; -import { format, formatDuration, intervalToDuration } from "date-fns"; -import { parseWarc } from "./scrap.js"; -import { S3Client } from "@aws-sdk/client-s3"; -import { Upload } from "@aws-sdk/lib-storage"; -import { BunFile } from "bun"; +import { formatDuration, intervalToDuration } from "date-fns"; +import { downloadList } from "./scrap.js"; import { db } from "db-datos/db.js"; import { like } from "drizzle-orm"; import { productoUrls } from "db-datos/schema.js"; @@ -23,7 +19,7 @@ const supermercados: Supermercado[] = [ ]; // hacemos una cola para el scrapeo para no tener varios writers a la BD y no sobrecargar la CPU -const scrapQueue = new PQueue({ concurrency: 1 }); +const scrapQueue = new PQueue({ concurrency: 4 }); export async function auto() { const a = new Auto(); @@ -31,35 +27,9 @@ export async function auto() { } class Auto { - s3Config?: { s3: S3Client; bucketName: string }; telegramConfig?: { token: string; chatId: string }; constructor() { - if ( - !process.env.S3_ACCESS_KEY_ID || - !process.env.S3_SECRET_ACCESS_KEY || - !process.env.S3_BUCKET_NAME - ) { - if (process.env.NODE_ENV === "development") { - console.warn("faltan creds de s3, no voy a subir a s3"); - } else { - throw new Error("faltan creds de s3"); - } - } else { - this.s3Config = { - // https://www.backblaze.com/docs/cloud-storage-use-the-aws-sdk-for-javascript-v3-with-backblaze-b2 - s3: new S3Client({ - endpoint: "https://s3.us-west-004.backblazeb2.com", - region: "us-west-004", - credentials: { - accessKeyId: process.env.S3_ACCESS_KEY_ID, - secretAccessKey: process.env.S3_SECRET_ACCESS_KEY, - }, - }), - bucketName: process.env.S3_BUCKET_NAME, - }; - } - if (!process.env.TELEGRAM_BOT_TOKEN) console.warn("no hay TELEGRAM_BOT_TOKEN, no voy a loggear por allá"); else if (!process.env.TELEGRAM_BOT_CHAT_ID) @@ -107,93 +77,29 @@ class Auto { const urls = results.map((r) => r.url); await writeFile(listPath, urls.join("\n") + "\n"); - const date = new Date(); - const zstdWarcName = `${supermercado}-${format( - date, - "yyyy-MM-dd-HH:mm" - )}.warc.zst`; - const zstdWarcPath = join(ctxPath, zstdWarcName); - const subproc = Bun.spawn({ - cmd: ["warcificator", listPath, zstdWarcPath], - stderr: "ignore", - stdout: "ignore", - cwd: ctxPath, - }); - const t0 = performance.now(); - await subproc.exited; - this.inform( - `[downloader] ${zstdWarcName} tardó ${formatMs(performance.now() - t0)}` - ); - - if (!(await fileExists(zstdWarcPath))) { - const err = this.report(`no encontré el ${zstdWarcPath}`); - throw err; - } - - this.scrapAndInform({ zstdWarcPath, zstdWarcName }); - - try { - await this.uploadToBucket({ - fileName: zstdWarcName, - file: Bun.file(zstdWarcPath), - }); - } catch (error) { - this.inform(`Falló subir ${zstdWarcName} a S3; ${error}`); - console.error(error); - } - + this.scrapAndInform({ listPath }); // TODO: borrar archivos temporales } - async scrapAndInform({ - zstdWarcPath, - zstdWarcName, - }: { - zstdWarcPath: string; - zstdWarcName: string; - }) { + async scrapAndInform({ listPath }: { listPath: string }) { const res = await scrapQueue.add(async () => { const t0 = performance.now(); - const progress = await parseWarc(zstdWarcPath); + const progress = await downloadList(listPath); return { took: performance.now() - t0, progress }; }); if (res) { const { took, progress } = res; this.inform( - `Procesado ${zstdWarcName} (${progress.done} ok, ${ - progress.errors.length - } errores) (tardó ${formatMs(took)})` + `Procesado ${listPath} (${progress.done} ok, ${ + progress.skipped + } skipped, ${progress.errors.length} errores) (tardó ${formatMs(took)})` ); } else { - this.inform(`Algo falló en ${zstdWarcName}`); + this.inform(`Algo falló en ${listPath}`); } } - async uploadToBucket({ - fileName, - file, - }: { - fileName: string; - file: BunFile; - }) { - if (!this.s3Config) { - this.inform( - `[s3] Se intentó subir ${fileName} pero no tenemos creds de S3` - ); - return; - } - const parallelUploads3 = new Upload({ - client: this.s3Config.s3, - params: { - Bucket: this.s3Config.bucketName, - Key: fileName, - Body: file, - }, - }); - await parallelUploads3.done(); - } - inform(msg: string) { this.sendTelegramMsg(msg); console.info(msg); @@ -216,16 +122,6 @@ class Auto { } } -// no se llama exists porque bun tiene un bug en el que usa fs.exists por mas que exista una funcion llamada exists -async function fileExists(path: string) { - try { - access(path); - return true; - } catch { - return false; - } -} - function formatMs(ms: number) { return formatDuration(intervalToDuration({ start: 0, end: Math.round(ms) })); } diff --git a/scraper/cli.ts b/scraper/cli.ts index 9507090..3e8af80 100644 --- a/scraper/cli.ts +++ b/scraper/cli.ts @@ -2,7 +2,7 @@ import { scrapCarrefourProducts } from "../carrefour-link-scraper/index.js"; import { scrapCotoProducts } from "../coto-link-scraper/index.js"; import { scrapDiaProducts } from "../dia-link-scraper/index.js"; import { auto } from "./auto.js"; -import { parseWarc } from "./scrap.js"; +import { downloadList } from "./scrap.js"; if (process.argv[2] === "auto") { await auto(); @@ -13,16 +13,16 @@ if (process.argv[2] === "auto") { } else if (process.argv[2] === "scrap-coto-links") { await scrapCotoProducts(); } else if (process.argv[2] === "scrap") { - const warcPaths = process.argv.slice(3); - if (warcPaths.length > 0) { - for (const path of warcPaths) { - const res = await parseWarc(path); + const urlLists = process.argv.slice(3); + if (urlLists.length > 0) { + for (const path of urlLists) { + const res = await downloadList(path); console.info("======================================="); console.info(path, res); console.info("======================================="); } } else { - console.error("Especificá WARCs para scrapear."); + console.error("Especificá listas de urls para scrapear."); process.exit(1); } } else { diff --git a/scraper/package.json b/scraper/package.json index 1ca6dd7..edaf0ca 100644 --- a/scraper/package.json +++ b/scraper/package.json @@ -19,8 +19,8 @@ "drizzle-orm": "=0.29.1", "linkedom": "^0.16.5", "nanoid": "^5.0.4", + "p-map": "^7.0.1", "p-queue": "^8.0.1", - "warcio": "^2.2.1", "zod": "^3.22.4" }, "devDependencies": { diff --git a/scraper/scrap.ts b/scraper/scrap.ts index 0698ffe..07a473f 100644 --- a/scraper/scrap.ts +++ b/scraper/scrap.ts @@ -1,68 +1,52 @@ import * as schema from "db-datos/schema.js"; -import { WARCParser } from "warcio"; import { writeFile } from "fs/promises"; import { createHash } from "crypto"; import { getCarrefourProduct } from "./parsers/carrefour.js"; import { getDiaProduct } from "./parsers/dia.js"; import { getCotoProduct } from "./parsers/coto.js"; import { join } from "path"; -import { and, eq, sql } from "drizzle-orm"; import { db } from "db-datos/db.js"; +import pMap from "p-map"; const DEBUG = false; const PARSER_VERSION = 4; -const getPrevPrecio = db - .select({ id: schema.precios.id }) - .from(schema.precios) - .where( - and( - eq(schema.precios.warcRecordId, sql.placeholder("warcRecordId")), - eq(schema.precios.parserVersion, PARSER_VERSION) - ) - ) - .limit(1) - .prepare(); - export type Precio = typeof schema.precios.$inferInsert; export type Precioish = Omit< Precio, "fetchedAt" | "url" | "id" | "warcRecordId" | "parserVersion" >; -export async function parseWarc(path: string) { - // const warc = createReadStream(path); +export async function downloadList(path: string) { let progress: { done: number; - errors: { error: any; warcRecordId: string; path: string }[]; - } = { done: 0, errors: [] }; + skipped: number; + errors: { error: any; url: string; path: string }[]; + } = { done: 0, skipped: 0, errors: [] }; - const proc = Bun.spawn(["zstdcat", "-d", path], {}); - const warc = proc.stdout; - // TODO: tirar error si falla zstd + let list = (await Bun.file(path).text()) + .split("\n") + .filter((s) => s.length > 0); - const parser = new WARCParser(warc); - for await (const record of parser) { - if (record.warcType === "response") { - if (!record.warcTargetURI) continue; - const warcRecordId = record.warcHeader("WARC-Record-ID"); - if (!warcRecordId) throw new Error("No tiene WARC-Record-ID"); - - if (getPrevPrecio.get({ warcRecordId })) { - console.debug(`skipped ${warcRecordId}`); - continue; + await pMap( + list, + async (urlS) => { + let url; + try { + url = new URL(urlS); + } catch (err) { + console.error("error parseando", urlS); + return; } - if (record.httpHeaders?.statusCode !== 200) { - console.debug( - `skipped ${warcRecordId} because status=${record.httpHeaders?.statusCode} (!=200)` - ); - continue; + const res = await fetch(url); + if (!res.ok) { + console.debug(`skipped ${urlS} because status=${res.status} (!=200)`); + progress.skipped++; + return; } - // TODO: sobreescribir si existe el mismo record-id pero con version mas bajo? - const html = await record.contentText(); + const html = await res.text(); - const url = new URL(record.warcTargetURI); try { let ish: Precioish | undefined = undefined; if (url.hostname === "www.carrefour.com.ar") @@ -75,9 +59,8 @@ export async function parseWarc(path: string) { const p: Precio = { ...ish, - fetchedAt: new Date(record.warcDate!), - url: record.warcTargetURI, - warcRecordId, + fetchedAt: new Date(), + url: urlS, parserVersion: PARSER_VERSION, }; @@ -85,28 +68,23 @@ export async function parseWarc(path: string) { progress.done++; } catch (error) { - console.error({ path, warcRecordId, error }); + console.error({ path, urlS, error }); progress.errors.push({ path, - warcRecordId, + url: urlS, error, }); if (DEBUG) { - const urlHash = createHash("md5") - .update(record.warcTargetURI!) - .digest("hex"); + const urlHash = createHash("md5").update(urlS).digest("hex"); const output = join("debug", `${urlHash}.html`); await writeFile(output, html); console.error(`wrote html to ${output}`); } } - } - } - - if ((await proc.exited) !== 0) { - throw new Error("zstd tiró un error"); - } + }, + { concurrency: 32 } + ); return progress; } diff --git a/scraper/warc.ts b/scraper/warc.ts deleted file mode 100644 index 4e719c6..0000000 --- a/scraper/warc.ts +++ /dev/null @@ -1,157 +0,0 @@ -const crlf = "\r\n"; -const crlfB = Buffer.from(crlf, "utf-8"); -const crlfcrlf = crlf + crlf; -const crlfcrlfB = Buffer.from(crlfcrlf, "utf-8"); -const warc10B = Buffer.from("WARC/1.0", "utf-8"); -const emptyBuffer = Buffer.from("", "utf-8"); - -export async function* parseWARC(path: string) { - const warc = Bun.spawn(["zstd", "-do", "/dev/stdout", path], { - stderr: "ignore", - }).stdout; - - // const warc = Bun.stdin.stream(1024 * 1024 * 128); - - // let buffer: Uint8Array[] = []; - // const transform = new TransformStream({ - // transform(chunk, controller) { - // buffer.push(chunk); - // if ( - // buffer.reduce((prev, curr) => prev + curr.length, 0) > - // 1024 * 1024 * 64 - // ) { - // controller.enqueue(Buffer.concat(buffer)); - // buffer = []; - // } - // }, - // flush(controller) { - // controller.enqueue(Buffer.concat(buffer)); - // }, - // }); - - // warc.pipeTo(transform.writable); - - const reader = warc.getReader(); - // const reader = transform.readable.getReader(); - - // const warc = process.stdin; - - let arrays: Buffer[] = []; - let done = false; - while (!done) { - const r = await reader.readMany(); - if (r.done) { - done = true; - } else { - arrays = arrays.concat(r.value.map((x) => Buffer.from(x))); - if ( - arrays.reduce((prev, curr) => prev + curr.length, 0) < - 1024 * 1024 * 10 - ) - continue; - } - let buf: Buffer; - while ( - ((buf = arrays.length === 1 ? arrays[0] : Buffer.concat(arrays)), - buf.subarray(warc10B.length).includes(warc10B)) - ) { - const until = buf.indexOf(crlfcrlfB); - const header = buf.subarray(0, until); - - const lines = splitBuffer(header, crlfB); - let i = 0; - const nextLine = () => { - const line = lines[i]; - i++; - return line ? line : emptyBuffer; - }; - let line: Buffer; - if (!(line = nextLine()).equals(warc10B)) { - throw new Error(`No WARC 1.0 header in '${line}'`); - } - - let field; - let fields = new Map(); - while ( - ((line = nextLine()), - (field = parseField(line.toString("utf8"))), - line.length !== 0) - ) { - fields.set(field[0], field[1]); - } - const length = parseInt(fields.get("Content-Length")!); - - const rawHttp = buf.subarray( - until + crlfcrlfB.length, - until + crlfcrlfB.length + length - ); - const rawHttpHeaders = rawHttp - .subarray( - rawHttp.indexOf(crlfB) + crlfB.length, - rawHttp.indexOf(crlfcrlfB) + crlfcrlfB.length - ) - .toString(); - - let httpHeaders = new Map(); - rawHttpHeaders.split(crlf).forEach((line) => { - if (!line.length) return; - const [key, val] = line.split(": "); - httpHeaders.set(key, val); - }); - - let content = rawHttp.subarray( - rawHttp.indexOf(crlfcrlfB) + crlfcrlfB.length - ); - - if (httpHeaders.get("Transfer-Encoding") === "chunked") { - content = dechunk(content); - } - - // console.debug(fields.get("WARC-Date"), content.length); - - yield { - fields, - content, - }; - - arrays = [ - buf.subarray(until + crlfcrlfB.length + length + crlfcrlfB.length), - ]; - if (!arrays[0].length) break; - } - } -} - -function splitBuffer(buffer: Buffer, val: Buffer): Buffer[] { - let bufs = []; - let rest = buffer; - let i; - while (((i = rest.indexOf(val)), i !== -1)) { - bufs.push(rest.subarray(0, i)); - rest = rest.subarray(i + val.length); - } - bufs.push(rest); - return bufs; -} - -function parseField(line: string): [string, string] { - const [key, val] = line.split(": "); - return [key, val]; -} - -function dechunk(content: Buffer): Buffer { - let actualContent = []; - - while (true) { - let until = content.indexOf(crlf); - const hexLen = content.subarray(0, until).toString(); - if (hexLen.length === 0) break; - const len = parseInt(hexLen, 16); - actualContent.push( - content.subarray(until + crlfB.length, until + crlfB.length + len) - ); - content = content.subarray(until + crlfB.length + len + crlfB.length); - } - - return Buffer.concat(actualContent); -} diff --git a/warcificator/Cargo.lock b/warcificator/Cargo.lock deleted file mode 100644 index 4aaf9e8..0000000 --- a/warcificator/Cargo.lock +++ /dev/null @@ -1,1373 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "adler32" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" - -[[package]] -name = "alloc-no-stdlib" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" - -[[package]] -name = "alloc-stdlib" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" -dependencies = [ - "alloc-no-stdlib", -] - -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - -[[package]] -name = "arrayvec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" - -[[package]] -name = "async-channel" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ca33f4bc4ed1babef42cad36cc1f51fa88be00420404e5b1e80ab1b18f7678c" -dependencies = [ - "concurrent-queue", - "event-listener", - "event-listener-strategy", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-compression" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc2d0cfb2a7388d34f590e76686704c494ed7aaceed62ee1ba35cbf363abc2a5" -dependencies = [ - "brotli", - "flate2", - "futures-core", - "memchr", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "backtrace" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "base64" -version = "0.21.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "brotli" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "516074a47ef4bce09577a3b379392300159ce5b1ba2e501ff1c819950066100f" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", - "brotli-decompressor", -] - -[[package]] -name = "brotli-decompressor" -version = "2.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e2e4afe60d7dd600fdd3de8d0f08c2b7ec039712e3b6137ff98b7004e82de4f" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", -] - -[[package]] -name = "bumpalo" -version = "3.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" - -[[package]] -name = "bytes" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" - -[[package]] -name = "cc" -version = "1.0.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "chrono" -version = "0.4.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" -dependencies = [ - "android-tzdata", - "iana-time-zone", - "js-sys", - "num-traits", - "wasm-bindgen", - "windows-targets 0.48.5", -] - -[[package]] -name = "concurrent-queue" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" - -[[package]] -name = "crc32fast" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3a430a770ebd84726f584a90ee7f020d28db52c6d02138900f22341f866d39c" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "encoding_rs" -version = "0.8.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "event-listener" -version = "4.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84f2cdcf274580f2d63697192d744727b3198894b1bf02923643bf59e2c26712" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - -[[package]] -name = "event-listener-strategy" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" -dependencies = [ - "event-listener", - "pin-project-lite", -] - -[[package]] -name = "flate2" -version = "1.0.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "form_urlencoded" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "futures-channel" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" -dependencies = [ - "futures-core", -] - -[[package]] -name = "futures-core" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" - -[[package]] -name = "futures-sink" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" - -[[package]] -name = "futures-task" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" - -[[package]] -name = "futures-util" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" -dependencies = [ - "futures-core", - "futures-task", - "pin-project-lite", - "pin-utils", -] - -[[package]] -name = "getrandom" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "gimli" -version = "0.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" - -[[package]] -name = "h2" -version = "0.3.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "hashbrown" -version = "0.14.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" - -[[package]] -name = "hermit-abi" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" - -[[package]] -name = "http" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" -dependencies = [ - "bytes", - "http", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "hyper" -version = "0.14.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "hyper-rustls" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" -dependencies = [ - "futures-util", - "http", - "hyper", - "rustls", - "tokio", - "tokio-rustls", -] - -[[package]] -name = "iana-time-zone" -version = "0.1.59" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "wasm-bindgen", - "windows-core", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - -[[package]] -name = "idna" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "indexmap" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" -dependencies = [ - "equivalent", - "hashbrown", -] - -[[package]] -name = "ipnet" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" - -[[package]] -name = "itoa" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" - -[[package]] -name = "js-sys" -version = "0.3.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "lexical-core" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe" -dependencies = [ - "arrayvec", - "bitflags", - "cfg-if", - "ryu", - "static_assertions", -] - -[[package]] -name = "libc" -version = "0.2.151" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" - -[[package]] -name = "libflate" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ff4ae71b685bbad2f2f391fe74f6b7659a34871c08b210fdc039e43bee07d18" -dependencies = [ - "adler32", - "crc32fast", - "libflate_lz77", -] - -[[package]] -name = "libflate_lz77" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a52d3a8bfc85f250440e4424db7d857e241a3aebbbe301f3eb606ab15c39acbf" -dependencies = [ - "rle-decode-fast", -] - -[[package]] -name = "lock_api" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" - -[[package]] -name = "memchr" -version = "2.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[package]] -name = "miniz_oxide" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" -dependencies = [ - "adler", -] - -[[package]] -name = "mio" -version = "0.8.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" -dependencies = [ - "libc", - "wasi", - "windows-sys", -] - -[[package]] -name = "nom" -version = "5.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08959a387a676302eebf4ddbcbc611da04285579f76f88ee0506c63b1a61dd4b" -dependencies = [ - "lexical-core", - "memchr", - "version_check", -] - -[[package]] -name = "num-traits" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" -dependencies = [ - "autocfg", -] - -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "object" -version = "0.32.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - -[[package]] -name = "parking" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" - -[[package]] -name = "parking_lot" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets 0.48.5", -] - -[[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - -[[package]] -name = "pin-project-lite" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "proc-macro2" -version = "1.0.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75cb1540fadbd5b8fbccc4dddad2734eba435053f725621c070711a14bb5f4b8" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags", -] - -[[package]] -name = "reqwest" -version = "0.11.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" -dependencies = [ - "async-compression", - "base64", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "hyper", - "hyper-rustls", - "ipnet", - "js-sys", - "log", - "mime", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls", - "rustls-pemfile", - "serde", - "serde_json", - "serde_urlencoded", - "system-configuration", - "tokio", - "tokio-rustls", - "tokio-util", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "webpki-roots", - "winreg", -] - -[[package]] -name = "ring" -version = "0.17.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" -dependencies = [ - "cc", - "getrandom", - "libc", - "spin", - "untrusted", - "windows-sys", -] - -[[package]] -name = "rle-decode-fast" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3582f63211428f83597b51b2ddb88e2a91a9d52d12831f9d08f5e624e8977422" - -[[package]] -name = "rustc-demangle" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" - -[[package]] -name = "rustls" -version = "0.21.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" -dependencies = [ - "log", - "ring", - "rustls-webpki", - "sct", -] - -[[package]] -name = "rustls-pemfile" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" -dependencies = [ - "base64", -] - -[[package]] -name = "rustls-webpki" -version = "0.101.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "ryu" -version = "1.0.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "serde" -version = "1.0.193" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.193" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.108" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" -dependencies = [ - "libc", -] - -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "smallvec" -version = "1.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" - -[[package]] -name = "socket2" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" -dependencies = [ - "libc", - "windows-sys", -] - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "syn" -version = "2.0.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee659fb5f3d355364e1f3e5bc10fb82068efbf824a1e9d1c9504244a6469ad53" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "system-configuration" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" -dependencies = [ - "bitflags", - "core-foundation", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "tinyvec" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "tokio" -version = "1.35.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "num_cpus", - "parking_lot", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "windows-sys", -] - -[[package]] -name = "tokio-macros" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tokio-rustls" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" -dependencies = [ - "rustls", - "tokio", -] - -[[package]] -name = "tokio-util" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", - "tracing", -] - -[[package]] -name = "tower-service" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" - -[[package]] -name = "tracing" -version = "0.1.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" -dependencies = [ - "pin-project-lite", - "tracing-core", -] - -[[package]] -name = "tracing-core" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" -dependencies = [ - "once_cell", -] - -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - -[[package]] -name = "unicode-bidi" -version = "0.3.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416" - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "unicode-normalization" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - -[[package]] -name = "url" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", -] - -[[package]] -name = "uuid" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" -dependencies = [ - "getrandom", -] - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - -[[package]] -name = "warc" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e44585619c04f9a4bcfdfbbbefff9e7c4e277a693424162b30c88aaf3abd785e" -dependencies = [ - "chrono", - "libflate", - "nom", - "url", - "uuid", -] - -[[package]] -name = "warcificator" -version = "0.1.0" -dependencies = [ - "async-channel", - "http", - "reqwest", - "tokio", - "warc", -] - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasm-bindgen" -version = "0.2.89" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.89" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.89" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.89" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.89" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" - -[[package]] -name = "web-sys" -version = "0.3.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webpki-roots" -version = "0.25.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10" - -[[package]] -name = "windows-core" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" -dependencies = [ - "windows-targets 0.52.0", -] - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - -[[package]] -name = "windows-targets" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" -dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" - -[[package]] -name = "winreg" -version = "0.50.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" -dependencies = [ - "cfg-if", - "windows-sys", -] diff --git a/warcificator/Cargo.toml b/warcificator/Cargo.toml deleted file mode 100644 index 723f0dc..0000000 --- a/warcificator/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "warcificator" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -async-channel = "2.1.1" -http = "0.2.11" -reqwest = { version = "0.11.23", default-features = false, features = [ - "rustls-tls", - "gzip", - "brotli", -] } -tokio = { version = "1.35.1", features = ["full"] } -warc = "0.3.1" diff --git a/warcificator/src/main.rs b/warcificator/src/main.rs deleted file mode 100644 index 8743907..0000000 --- a/warcificator/src/main.rs +++ /dev/null @@ -1,199 +0,0 @@ -use async_channel::{Receiver, Sender}; -use std::{ - env::args, - fs, - net::SocketAddr, - process::{Command, Stdio}, -}; -use tokio::io::{stderr, AsyncWriteExt}; -use warc::{RecordBuilder, WarcHeader, WarcWriter}; - -struct FullExchange { - socket_addr: Option, - request: http::Request<&'static str>, - response: http::Response>, -} - -#[tokio::main] -async fn main() { - let mut args = args().skip(1); - let links_list_path = args.next().unwrap(); - let output_zstd_path = args.next().unwrap(); - let links_str = fs::read_to_string(links_list_path).unwrap(); - let links = links_str - .split("\n") - .map(|s| s.trim()) - .filter(|s| s.len() > 0) - .map(|s| s.to_owned()) - .collect::>(); - - let handle = { - let (sender, receiver) = async_channel::bounded::(1); - let (res_sender, res_receiver) = async_channel::unbounded::(); - - let mut handles = Vec::new(); - for _ in 1..16 { - let rx = receiver.clone(); - let tx = res_sender.clone(); - handles.push(tokio::spawn(worker(rx, tx))); - } - - let warc_writer_handle = tokio::spawn(warc_writer(res_receiver, output_zstd_path)); - - for link in links { - sender.send_blocking(link).unwrap(); - } - sender.close(); - - for handle in handles { - handle.await.unwrap(); - } - - warc_writer_handle - }; - handle.await.unwrap(); -} - -async fn worker(rx: Receiver, tx: Sender) { - let client = reqwest::ClientBuilder::default().build().unwrap(); - while let Ok(url) = rx.recv().await { - let res = fetch(&client, url.clone()).await; - match res { - Ok(ex) => { - tx.send(ex).await.unwrap(); - } - Err(err) => { - stderr() - .write_all(format!("Failed to fetch {}: {:#?}", url.as_str(), err).as_bytes()) - .await - .unwrap(); - } - } - } -} - -async fn fetch(client: &reqwest::Client, url: String) -> Result { - let request = client.get(url).build().unwrap(); - let mut http_request_builder = http::Request::builder() - .method(request.method()) - .uri(request.url().as_str()); - for (key, val) in request.headers() { - http_request_builder = http_request_builder.header(key, val); - } - let response = client.execute(request).await?; - - let ip_address = response.remote_addr(); - - let http_request = { - http_request_builder - .version(response.version()) - .body("") - .unwrap() - }; - - let http_response = { - let mut http_response_builder = http::Response::<()>::builder() - .status(response.status()) - .version(response.version()); - for (key, val) in response.headers() { - http_response_builder = http_response_builder.header(key, val); - } - let body = response.bytes().await?; - http_response_builder.body(body.to_vec()).unwrap() - }; - - Ok(FullExchange { - socket_addr: ip_address, - request: http_request, - response: http_response, - }) -} - -async fn warc_writer(rx: Receiver, output_zstd_path: String) { - let zstd_proc = Command::new("zstd") - .args(&["-T0", "-15", "--long", "-o", &output_zstd_path]) - .stdin(Stdio::piped()) - .stderr(Stdio::null()) - .stdout(Stdio::null()) - .spawn() - .unwrap(); - - let mut writer = WarcWriter::new(zstd_proc.stdin.unwrap()); - writer - .write( - &RecordBuilder::default() - .version("1.0".to_owned()) - .warc_type(warc::RecordType::WarcInfo) - .header(WarcHeader::ContentType, "application/warc-fields") - .body(format!("software: preciazo-warcificator/0.0.0\nformat: WARC file version 1.0\nconformsTo: http://www.archive.org/documents/WarcFileFormat-1.0.html").into()) - .build() - .unwrap(), - ) - .unwrap(); - while let Ok(res) = rx.recv().await { - let uri = res.request.uri().to_string(); - let req_record = { - let mut builder = RecordBuilder::default() - .version("1.0".to_owned()) - .warc_type(warc::RecordType::Request) - .header(WarcHeader::TargetURI, uri.clone()) - .header(WarcHeader::ContentType, "application/http;msgtype=request") - .header( - WarcHeader::Unknown("X-Warcificator-Lying".to_string()), - "the request contains other headers not included here", - ); - if let Some(addr) = res.socket_addr { - builder = builder.header(WarcHeader::IPAddress, addr.ip().to_string()); - } - builder - .body(format_http11_request(res.request).into_bytes()) - .build() - .unwrap() - }; - writer.write(&req_record).unwrap(); - writer - .write(&{ - let mut builder = RecordBuilder::default() - .version("1.0".to_owned()) - .warc_type(warc::RecordType::Response) - .header(WarcHeader::TargetURI, uri) - .header(WarcHeader::ConcurrentTo, req_record.warc_id()) - .header(WarcHeader::ContentType, "application/http;msgtype=response"); - if let Some(addr) = res.socket_addr { - builder = builder.header(WarcHeader::IPAddress, addr.ip().to_string()); - } - builder - .body(format_http11_response(res.response)) - .build() - .unwrap() - }) - .unwrap(); - } -} - -fn format_http11_request(req: http::Request<&'static str>) -> String { - let start_line = format!("{} {} HTTP/1.1", req.method().as_str(), req.uri().path()); - let headers_str = req - .headers() - .iter() - .map(|(key, val)| format!("{}: {}\r\n", key, val.to_str().unwrap())) - .collect::(); - - [start_line.as_str(), headers_str.as_str(), req.body()].join("\r\n") -} - -fn format_http11_response(res: http::Response>) -> Vec { - let start_line = format!( - "HTTP/1.1 {} {}", - res.status().as_str(), - res.status().canonical_reason().unwrap_or("") - ); - let headers_str = res - .headers() - .iter() - .map(|(key, val)| format!("{}: {}\r\n", key, val.to_str().unwrap())) - .collect::(); - - let crlf: &[u8] = &[13, 10]; - [start_line.as_bytes(), headers_str.as_bytes(), res.body()].join(crlf) -}