From 16d6a30c04592ff1ceacec35e91d98d77d811a04 Mon Sep 17 00:00:00 2001 From: Nirav Patel Date: Wed, 19 Aug 2026 00:11:38 -0400 Subject: [PATCH] fix: send explicit User-Agent (Cloudflare 403s default Python-urllib UA at id.shre.ai) Co-Authored-By: Claude Fable 5 --- .../granthi_sync_client.cpython-314.pyc | Bin 23298 -> 23401 bytes client/granthi_sync_client.py | 2 ++ .../__pycache__/granthi_link.cpython-314.pyc | Bin 18401 -> 18494 bytes server/granthi_link.py | 2 ++ 4 files changed, 4 insertions(+) diff --git a/client/__pycache__/granthi_sync_client.cpython-314.pyc b/client/__pycache__/granthi_sync_client.cpython-314.pyc index 644b42f79523ab83e5fd84968af3c65a1340a701..a8eceaf447577ac7ff4a0df5b73b8d428a659217 100644 GIT binary patch delta 2800 zcmY*aZA@F|753}vd+|3Az5+PLF(Kdvmo-o*A5BQgM=~H-#wH;nwG6(1gR!mmUZA*X zDb>>SM!*4ad9bp3s& z|Ko7in1(t=1-VV%>xOf74>a0cP}g1ZZQnvmSbBKcxCHxpJ#gDzR#JX28!l*Dk1A`e z#t6t(8LHR_@?L zLyoZHkR9%|mkG|W3m!PD@z^R?bCo@+$UL}bT28Au*EEl()tO{aSxQef!Jz9kPlaYl zBqvqPuE=Uao{G<>RIOmNH$1X`_yF8-)q>moE^C0R?tuL%JasqzmG8p?cU9S4i}l3t z%J8YdpAP-D{!HbE{>~eguKec0BW(73aYJvZ>3qAVmx&k3tSDdbTKg+Z7wXFicbO3{ zGDmN*?V{6y){DggVQEc&sc^Bmy01jIRI(lAOC5}`)7@VvT(*&Xxlkmm*xKJITt;gr z+%5Vy^TW;J4zU|!JCZNo^n}^bg(B}H@I$!NzfBKY!1Z>Yj~C)ob13lzIX0O|PbH`M z5NhQ78>R1?*#S6I;kAcos}A{>Dy}lr4p#1{>7$L7Y+Rku#H5l)a(;NjFCg$|VYRYO zoJGyC{JF~CF|68Bbw3Ni2i0|sXUXv>K?8hIT`MXm9?w^L5@sgDi{7Y9KWrSe0V}@g zuD4W5>RaF|Z>P9|;^}-xjVQ3^q1#{XoG04?LWD2Dg#SBi3BcbgQGR5B&UVtSwfGv@!pK(qL3bh?wj7Wjw2n)B}lw=xFs@#6{h6g<=P%r=Tc z6Ow6Fv#7~ASre6%EN24}Z=eHO3C_YVo1PReqxfn5e$y>M`VDCp;CyrQ6FX7NZAvB6 zv%aY~9-iY7m{Zg7pc}$7NlQQ-Sn+j$Druyh4y5cmYAPrQ(Vjqj|#9q|6X3 z5nM;exhY(%?o=j~khw2s@dbDJ0+o7!MvYp1!wCKh+NRTThNPPanwiU*pv+Hb)`_?x zr{i-nrxxSH4&xU7Op;#N5J?L5TSX`5B!5%+fK9JAr?MI+(90jG_bpnkcU-Q^C*Hwz zb^a$^XUyV#6!+#MyWcdk>+t!W@@2|fuRwt5H89eBnEhYSp0oAr$0^$1+vDRA@~5vx zPU;PZhr>QTf{O!4^b=%x6(LZlR|JWd;i{a_y9{THD$gkoJBI63DI!+zlaytNktInl!S%fB%7qQKhrApFA{6CXIx>N9#WjoJYW@h?)EX zf6M&w(JtCKVQ3siqE|7G8z5ToYES&d8X@Z|(wx6k0(pU}Ynh@i1R&YsSw zKEuhNMR7W_P6=g0uirM?&8d2tn3k#kmf-q#Gpqx44Gghk@Y(>hbf7iBG%|%5qv`MS9ou5b34s&O~@s)-y#XISF`ZU zqGIsnQ`+z~DW%0^LY-0gf5AOeD>|^dQu)@QafuZIjI6Oa=#4bC5{q+EFi3>W*@D3= zPcG0bAhP1OR?ToZrt*0iQ`kiPSwv6{KZ|UUj5S<|>|*6$i`F@GTNybtKzsDC$hY82 z;H_wo^}&_sW9$a}E9ze+#_|sc=z2KC#SfD7I>B26ZzE`S9O#N1i}PuPZ$>8^nPk*h zmVZP~vy#<>X`a<-ph&3FN07k+qwy1{d>OYYw-8=3-L@9pwB}bwKWAeaS_~ikqIPNp zu~;HAiKE?%u9`$W+}gtZ6L4nil32l>{%03FfB3}z0sgbR;{X5v delta 2782 zcmZ`)du&tJ8Taw^wR7z_8IWKIPU0jajtPN;yddGxj64=XNa`ep&;-laH^~i-?VWp_ z1P_gLE#;3@D&renyZy0E-K161COWHKHI*_7O*J~ENl4v#)=p`=b?TV*{A1dqbl-O` z5lq@F`FDTkJKuL6-|Kwz68pkS%-c}pb=&ZFr{UaO=mqaSh24ZfrPb+ByKOc&N zJFGVN>qj~mNMM!C~+P=7j|~oVR_wVS&1kkKB#!O%pOr7 z)?ES%o**lPg3bzf#j~&U-mz@9k+S=%!{-bAu&vO`Ohd<5;YbBU3WJsZQ+ds7Bmmbo zZGf+b6?nPOE4#u4leKWOu#MGU^p?uXG51IVyjQnDa)&+8znPKE~LDZpbD;(RI~lCT2dh&MnOC;m0q=nhL8$JjL+!8k>TmM zPGPOvx-Gzq$!d5FGWk2cHyIm(A8u}_>@|%tF=JN9nx4=&pIFliNqh=eS*<*Wl3c!_ z>}7_Y{LPkrHVoVSwVo+b)Chtw>93JF(#P_T`xADSfR8H1gXWHppfps#Nm)3#I-fRF z;XKJ>srW3PC1VZL$}V{s=~MY{SISaNj#TA&mCvX-rLl2(x-p$fp5_KAXA#Eu65Oh8 zVoPwhy4QJ{#0xM`Q{A|TG$eC6hjrU!V#f%!BZOS$Dfs6|a0Z^KsbcN$qnc{@NfbPv zf3M~VDL|(cN+!k)&Ct>*PX6al5%>wp;e4<|p*stQsv}hJ`JlOUjex!WJkY#5^9mZi-ULb9ozmSv0eG#jw;43!obc1 z>wxd?Jh+v16_S=Rgu~G0RUzw1Rn3H)JV?v65xfYcO>OcD(hu{)O>axi?~ybMJ6cP~I(t@0-g};e_ zQPT~sWrQ=KE@*L;U!@sxjBsW%iI}1C07)nl`KJgdQ!x%F@FToA&4?w`WYkEXQd19{ z{Sb7wmCLtL$B~b>Ey(N=h|ci=^9HnSPT9H8ypyY$G^TSZh7NFLxVAvs-K2$;cru+* zqgkHRp2d2$ZbIo{T_*-hU42oys~PW{YeqF1QCYZVF!zjEt&b;Y7ZH|O2^F5Be~kUo^Zdf-|6*;`0+^622eNFb+l2Ie(g*HSa)^-V{Fn8nRo z-*j&{shgOM+g<)%N#w;4K-nwmgti; zL!H;})d{JZUNe0|waNdlTTGA0_nZOc2ixV}qkdoh*ufu26Ldl093AK%I5K8A`bAod zG=w9a!c1PJ@il_i5b&Ioviv%NPFvPlofA`SJ`r7v8Q8J@jN*xWynj(@p{mIhP=Tq5 z&OlBIJQT2!@Mk!|e~KVjDCbV4jew6oPk#lk58NFSV%InZT*(m zhX}$M%VgA4Ldcl^Gpdm0V@qbQ7gA2k{8w60ItT|(FX~o?{f^f7m$}BGmM~^@{!chP zR3p2w?&k8}9GY~pBDg#H0!zZ>vF&UM-W~IGQ+f-xZlt*yHF#FVJFKHREhZ>M$Q3j; zX0j)fT3mQ6wdq(=S1}5f9<+_`XQg0_*LqBw5;6?Jx5kev!i6a}Ixu_$q(~#{h33dM zb{i%m)nUqS{$m1)6sHsN2r+8P{A&cyAqY3NcwLRsW66D}gl&~31QQ;_bCDH{-NRxT4WSIv$Pka$F4Gx0tTBxAH1dGrPjCi2Z?J zjKDn2HDsa?drwk3xdW3R&AA_XCbpjq;2M0IX7Lrt#8QbYc5C5MQwti$H_41^KP@vs z&_(bH!4-lUGJchqSwChQH*`D`t`hrzfGXz! UzsA9Ld_^v0`~JEc-amf+KOhaWm;e9( diff --git a/client/granthi_sync_client.py b/client/granthi_sync_client.py index 70b373b..f567271 100644 --- a/client/granthi_sync_client.py +++ b/client/granthi_sync_client.py @@ -64,6 +64,8 @@ def http_json(method, url, headers=None, body=None, form=None, timeout=30): """Returns (status, parsed-json-or-{'raw': text}).""" data = None hdrs = dict(headers or {}) + # Cloudflare in front of id.shre.ai 403s the default Python-urllib UA. + hdrs.setdefault("User-Agent", f"granthi-sync/{VERSION}") if form is not None: data = urllib.parse.urlencode(form).encode() hdrs.setdefault("Content-Type", "application/x-www-form-urlencoded") diff --git a/server/__pycache__/granthi_link.cpython-314.pyc b/server/__pycache__/granthi_link.cpython-314.pyc index ae8b1d1b408b707b90713e3992eaca30aae6fe1a..eb10fe5ec8c3b9e6ccb8ebbaf514bce84115cbe7 100644 GIT binary patch delta 2876 zcmZ8ieQaA-75DY?M{LJVoY?ttoVc~?#OV?@-_4RV=^7`r&63nD>Bh2VuKkj{*70-i zdr8}LrJaDTodnBvhBm&Y4zy`Q1v;{oNeC!yQ`U*W%0R%=kO~C>(gYQMpwSh^IqxNH zwMzF#)_4rD1bY zn6QureTAkLbDPeg1X&6KGk|MRY7LDDf1 zhNFe;f#|AyRa$F$z?pPD;24X+)oOpRu#*`Yan@>{GY3s!lVs`^f+mT@-0)H1mcWAZ z(~8I&H&2T>^`?88r*i6y)R>iW`{Qt*TWa=emW-5EHK!t~8F4B#msK_Ucp|xT>*$DP z*{8@k&6=5;%`2Ks%%$aw2=BUESP|Gf+dABMwkFK+ET>#*mc4T3F!vzIUHW<^!xc^7 z;sMRVMJ3ORNmK(TJTG-MAvu7*@)-=^xapd!==i{UuA)Wzv+hOrb1m<>YK{+FvlKi& z`q=2=@ag+st2ujxX2aLXp^#gYP~F9r$*{ichNGQw^% z;U?FB$8pJFLFpxrK+Emr>dU z|0sULRzaRe;fyy@(ukyHo7|gHq%`lq#l!F?ugs>tl`Ju{M%d{KvuQZ!%dk#(&vzY* zecnHjpl~_Gt2re_$|-6pmlk;`GGZ27+6G!){E zkSdF_1MpOtinb2~eM?p4&$7zHbH~Nmy1_@!o9@lH5@a-@k zu44=Ee7J!<3Rl9lrAJY&S(KSnbIi>jq8%gfVYp$N9u&>td&lbrXYftXYk|0i@9dJw5tq zqohH7rU}>^n*Csk=cL>;PZIwTg8c-aBiKRk48azJ*h)V2-03IlN&PyCG(qGX&+SLj zH7%)PYNc)I_?5)!d8M8seGAPSt#}x5r^x4}wAe(Pb4zl=EW_yju)f+{OqTfq!B+{2 zz|jup@pJQD$B)G=5Rsu-F|Nm(%ys{hokU1K3mMdXJG#t}3}IxFYINt$jw@QbFh;g9zmO*=Vj zWNM|FdZz9~al5R#(UscjX~EiVhzHr#rIGk{R*tV0-50%F`URrw^8q-!p{H|*NUD`q zh%-Z#(zBvEBWH}t(M7wfe0t?xAl|nj+?*()%=4~Qn1X}N_`K;$_+@hgdmnB#4_J8t za+dCI8D;f!Avit1H$7YAoQm&7X*mXEBCODV5;lLG=EE5=+Ln>x9CbBK7NB@c8p;%ER8nR*`v5XtLg6yNE z@vbLW@Ec@=u8`(QWit5QDU*uI@vh-;Ou&EdEyoo3yVo%{bazLOQ6XNTt9pjEeTU$? z1m7dj{h`!o9-OiBBA>)xk>s4=^IN2ImEgAouM&KpUZE*Fs zukIe~?-&~-E-7ht!*@lq%*cw0RhPM{2@0Rrn9Bc5YS$5raj`Nj48QR;)1&@3ioNjj z{=Z=>yuSH4Gy5Wp3_Mt@54{ZSKS^*3elW0>{SdT)b*${^M7T;1<#`g30jws~SYuOs z5PB2k#yzo72;UPN_(4d4q_)& z0t~i`dchpiqB<;3PoqHhcfY~fc_|S5T#$vb3~D+x<5ug{GOJSdt-bS d^vuecxvaQ}d!cbCXDwsB|7wBLL%kN#`9G)lzij{j delta 2786 zcmZ8i4QyLi754SBoj6XMEpg%{c4|9uoH%LXCb65ONn5Xp({^M@$g;9RSmgMrTS6&O`I!~}FdS;r<#T7?jxClIs~2n_@U#Dun0aL#>h zI%dhA&OPVed%k=A-lZ?It7n+I+g(#-!QZ#Kzi{L$J1)4t<75+X(HXColtGKdZ<)7} zm3}j}$N%859+KeF?d^8^A;*jpo*8O%#>*Q5@OCHw?}a?@QkA{hHfS?Xl`4F~aK5U+ zuFu*Bt-!{bq{>5;5bX58%X=zqB_}Sf40_W=^47ur+rpWkLuuviAH4vXAO&ndZP9kUhlA$Yzz;S1li z-?RoS_f^eS-sha@fIv^9e~_6QVr;;=Vr{XsSyao2)M8Ot)CGMtV{oQM?erKnS)sa?tbQmdG}quYP{BvR(OuPNU|*!{88n$gfi zP>LJ;O@F2lh6LF&dR#s zlBbO+aLpsL1nh5khq<7;aXv-w;```im8z))O-~mx3a>*&)W*k1U!Bfm6ir*ui$|3L z_mj$|7M6+{6;>n?4DxPxt1-rk@L{9Q5*x?7=NU^vOOuyPLZT_`z8Cjt5^WZHvrXM> z6`<)!&ImYJDzXz_j9QQ5b5yMqFv5?M{ zmeY%hUgrCGWN>QRE_NDzx-G`;g}-j=W&Pj_-0z@*;SpF5EX*cJ{1_Fdc!f!2p6vYu z6bT+7AbLDXP(sk02oZ`U{*vf(M=;7BgHH#qAl2@WYGt2-C)CpH= zxZ2jiPJ%PsHL!-3skJ+VC74$WdT=SN<`g;Dd0=jCCdeN^yJ6Fo(|yqzewgl>gr#s- z=oWXX8cu28NrY%c`4w;>+~M7#tW}_`%oe%+J>0>b0dM;U$hAJ=ksN2}{6o+am9fp9 zh<m=u&1!)_MQ<0vDAByGf#=Go;Ds{YJ%!G%u)yET19${RAq(DS~N&CkXCD zh?XNQqAEO#aDNR=hNN(gesQ`OuB@sn>2eK|`*O%d#6?+N>hiIR8%9^2;X4j&_ggHTYd`hhMb<{;vYyY8GHN#?wv{d# zSjC(fhH|Pz7;X{Y%9-#|PMml%$7uoIjQQBx8!yH_!Mq7{hz%sNAv%hJ%lCn=Z*(w4 zBBjEp#`&PDnY^Me7iBXs)OjDtj!4YYq&o+v`%<+ulsJCCOpxJP->idt@j=+t-^Jbq zrGLD3ttQLU1$|lV$*F~-v5g<}PqWTS+C`1=zI&`#(3OJTGpQ7^`tnq?ir16TL(l;2 z@gNJqL_E?;^UCaesknH=s3@gZbH%h=9s&`XRHx%j>~C-`eiG+NDDeXG!>d_VsXIEq_yrxWTlz>z~{>40e>9YzJ3`s z{B?w>sN0aR1;v-e%$wlciZ;W}m#{Cnk2bfF!a28EQc|23IVTeQ=LDMsW++j@?9=lM zM@|IcV`D_4PeLTvhPkE8;xpvp!p!tNb4Kj}ELL>ZTUOlI*cg74CBBZEL@OEYv@CNP z@S4uC=WwhFKhjbjzoluO)y!EK>B8vok#_uUJT($&qZ~d|fSa4Yeciq@MYCXNf|NxFz)!ry}BWa8%Ov&o%~anf$W?~|eEJ0xC1FsDIz7?@lP zJNEE#h5sAPwGh4Y&w@?H0;N&UM)$sTEBg|hA3uDX7;cMn(Zd9ffG5?;UWCC^JFAD! zrrMH%_&3N#S790{xdvO}M8uGeDyxQ7(?tTeI@7|>(gA`FcsX@F8Kb2rp#PA>7#_89 zh39GY7lH=~J|OrLf>DhFBd0F*;t0f|^1}6rgz^R%oLNPmEM~K45X^3nvLaK=m#8Gg zS3wMzI9(+gS45S#o1{d-e?v=(y;*IQqxqt|l2i8Z+u+gt1-pms{%0@T*uUFGd;SON CMxNyW diff --git a/server/granthi_link.py b/server/granthi_link.py index fff0c34..f12a717 100644 --- a/server/granthi_link.py +++ b/server/granthi_link.py @@ -69,6 +69,8 @@ def http_json(method, url, headers=None, body=None, timeout=20): """Minimal JSON-over-HTTP helper. Returns (status, parsed_or_text).""" data = None hdrs = dict(headers or {}) + # Cloudflare in front of id.shre.ai 403s the default Python-urllib UA. + hdrs.setdefault("User-Agent", f"granthi-link/{VERSION}") if body is not None: data = json.dumps(body).encode() hdrs.setdefault("Content-Type", "application/json")