From b6f188b9133c4203aa0613129ccccd459ce8c21e Mon Sep 17 00:00:00 2001 From: karuo Date: Mon, 2 Mar 2026 00:25:50 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=84=20=E5=8D=A1=E8=8B=A5AI=20=E5=90=8C?= =?UTF-8?q?=E6=AD=A5=202026-03-02=2000:25=20|=20=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=EF=BC=9A=E6=B0=B4=E6=A1=A5=E5=B9=B3=E5=8F=B0=E5=AF=B9=E6=8E=A5?= =?UTF-8?q?=E3=80=81=E8=BF=90=E8=90=A5=E4=B8=AD=E6=9E=A2=E5=B7=A5=E4=BD=9C?= =?UTF-8?q?=E5=8F=B0=20|=20=E6=8E=92=E9=99=A4=20>20MB:=2014=20=E4=B8=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 02_卡人(水)/水桥_平台对接/飞书管理/SKILL.md | 3 +- .../飞书管理/参考资料/3月1日日志配图.png | Bin 0 -> 26877 bytes .../飞书管理/参考资料/卡若的飞书日志_说明手册.md | 11 + .../飞书管理/脚本/.feishu_tokens.json | 6 +- .../水桥_平台对接/飞书管理/脚本/auto_log.py | 12 +- .../飞书管理/脚本/write_0301_feishu_log.py | 236 ++++++++++++++++++ 运营中枢/工作台/gitea_push_log.md | 1 + 运营中枢/工作台/代码管理.md | 1 + 8 files changed, 261 insertions(+), 9 deletions(-) create mode 100644 02_卡人(水)/水桥_平台对接/飞书管理/参考资料/3月1日日志配图.png create mode 100644 02_卡人(水)/水桥_平台对接/飞书管理/脚本/write_0301_feishu_log.py diff --git a/02_卡人(水)/水桥_平台对接/飞书管理/SKILL.md b/02_卡人(水)/水桥_平台对接/飞书管理/SKILL.md index 3fc0dbad..9601eb08 100755 --- a/02_卡人(水)/水桥_平台对接/飞书管理/SKILL.md +++ b/02_卡人(水)/水桥_平台对接/飞书管理/SKILL.md @@ -48,7 +48,8 @@ python3 /Users/karuo/Documents/个人/卡若AI/02_卡人(水)/水桥_平台 ### 2) 写入中:只允许命中当月 token(强制) - 禁止固定一个 `WIKI_TOKEN` 写全年日志。 -- 使用 `MONTH_WIKI_TOKENS` 维护月份映射(`1月 -> token`,`2月 -> token`...)。 +- 使用 `MONTH_WIKI_TOKENS` 维护月份映射(`1月`、`2月`、`3月`…)。3 月文档 token 来自环境变量 `FEISHU_MARCH_WIKI_TOKEN`(在飞书复制 2 月文档为「2026年3月 (突破执行)」后,从地址栏复制 wiki/ 后的 node token)。 +- **3月1日专用**:`脚本/write_0301_feishu_log.py` 写入 3 月 1 日日志到 3 月文档(继承 2 月 TNTWF 结构、不含 2 月内容),并尝试插入配图;若 API 插入图片报错,可手动将 `参考资料/3月1日日志配图.png` 拖入飞书文档。 ### 3) 写入后:双文档校验(强制) diff --git a/02_卡人(水)/水桥_平台对接/飞书管理/参考资料/3月1日日志配图.png b/02_卡人(水)/水桥_平台对接/飞书管理/参考资料/3月1日日志配图.png new file mode 100644 index 0000000000000000000000000000000000000000..7a0ba1537f7160774bce6bd18ab4f013652fc9a2 GIT binary patch literal 26877 zcmbUId011|7e9>dBqTs&5II^1gA58eT2bUEVbTNyl0ZU8aH41x6cbcRL{YHX0E(I- zMu;L2@CXTm7N?@cD*a+LBGxDbL`9rHQN*DX)T*uDck%tb&-*^l{p;RqpJHn;Ih(!q zTAykE_wIimqw&HhK@_4;5Td|8=)d<-1R6ii#?FR0-padvaHm4_NC8n%iIrb(LhY1s$COY{! zJNvEV1@cz@|NQH}Ey%%&nnx?7QM?eFa;`Y~cBe!I#5-jf}o~|KabCpT^cjLA3v~Ecp6=7WV(KE(cf_)xv^i zVL7%g3UxF5OLMTGd-^jb@Zv33DjmIM=UQRm`;VT!WbGXw{c~dSh7RVWDa4bh!(&VP z-^%{KTUg%zUn~267WV(Hs|VT8D6n}n2Q(kuH96M|i=FB{;$!%@9GQF+Ts?`H;Q=u* zJu2@og;E$fGm#sJ9q@Q86Cs~4`Bgl+*`ggOY}uhw7UBu<5a}8Wy&8#9&^;eZkSL(u zz|g!S=~cNgMQjSU=JY@*S<_BcFK?t7{p84q?J%dRzVam;xP$z-X5^#fIun~~m1<-i zRv*CaZ=UH)(v1u)D}sx#rlZk0R-}c#N{!eiPvSgD!&XRH0cxZOHM8s!qe3Or;X*S@ zeAhrzBZfa;!N(+2*-jsv3!h)CMu~|5W1nfLc}G;KCaKvb3*TDMLRV`Egn@3l+&rq zSgCtsBa$h_dID(+v>jaAYL3C^iP_jvbvf;JY~-b4o7kj9mDVhw23CV~f9AM(?v5t3FBLYueG;ydpNdK0*OJ+5oN3tcKB-9jL7H;V__`8Y~ zl_Qx{$}yM_l8%z@a$nd1>pmSWr{K0Tg$md$M-x`&46pks^dm7M0ySZIB@L)gWiz5q zz?VBUc2^SxD%O9I^0xzjRG#gc|KK~rhSmm@V-;#Pr!>z@Oh&jOV5}0& zEJ-GhWOS%A3`R6p9n!(4mg502IwT%#+)TDpUCpcjowX57^^u#1&obnzJ_f$cY0rZ_M8D}6*qM$;jAW(0-TB@)`g!#ETLdWCU>9NLS z6*HbsXOr~TqIB(-uB#YQnaz|)6k;HLF<>eQ^}PYp+BKqA@#=6Tmq7YY(&y7-uNmCf zlx!oruc%jI*?>6G0o|5CXhC*t{bNZGNynb3dE!1OkZNp2YN-JQ`e@*p3DhYNL&>7` z9F}mQYddw0haoMUO}STVlUxSRtmJPo_+n-`#aeF|;>#&K4}1aDrQ8?*c$~GN*%fMsTLiTY>GW*RtRbaR1$ys5HgE~BIhquIb zhSPuwv*{?5)#+)92l)RwQZ*K@hJ9uS>8T}xXrCg5>fva?ft?!DrPvIsTMaPm9*ciWpPN0TSPPNQcKlYzvbGQ z{FEXS9;Bz`_LUG!djc_PnQL+~NID$PsuBXZHx`sOFjOwlGM?U5Le<4epA(JfklsL0 zxYkj){4Mkd5niK10fI_}H8iLde393PpuF7{aXQoie31uME_GMbsFYkgS7yA)BgjC~ zookD<9dS-n6;s@(hwt>ostS|g!~WzNOmpGSA5nY4&H4Y#-KJET?oi2Hwf+He4kD%ved;U!$xxT z)Ji&H8(s@w-O>U2g=EN$q5PQ=lu~;R2UpotCk)v_yOrngm2u)biAk40r zHK1~iiDJLzB12z^!I?yAG2Jgj7ar11TT*#1CrhEe%=~u>lsJC(^X(bOe zC$X2dXqHlpQG__Ez%zMzZyidE7epeq{;l9)X)|&rD;4&M_-^X~joNQ0TTl>6#%w$qLg(YnsPMA0bHYBM9Ln36Zd&y13zTLx!?o}^zh67C9-2Wd$Y zTM`{{Ni=Tj48Lr>kCw&7vAn`z0oSe?V@lYR%LdOO9uyTiZ_rb1eg|eycPNCN+!D4$tlp0jMLOI zu5El=HC9H_NtSr@F`HsVGB?HENWl6bNFtOtv0+994}+qNz?;V}Z&|7%YRzrA^Y9Sx{B;Qs zs&rGWyEebUgBh;i!}$nTKu0#KC?z~Bwd6>mg;Om>WVi*JVr17m4^#9q8J=kY#yLeI zpKZA6pK>W9Y|u_&NvO1=`UfUYU#z2zv<@~W=L^&pAt+uKTNr4}+DT8dio@R7560Cp{uANVDzCedE zh}6T8$hKSS3UE-!fWuXD)(?kfKWcEp?Y%S-+8+H)+^R~2l@!V%LtLd2s(a%auaeM? zeCRq;0g9<@y-Iih#WYgb60vEnrk%FOG?khcz_k|Q{_1#Wng%bOoFX@Qzzp-R$rRqx zKixFezE}Y!4E4&CQU`u?GYs1c3dMuSS*bqf2NLv<^IFpA^9mq$-5 z`t_HwuDeLn@i1S`gnD`xP@fIi@gr3EoP?0O5yKVo8X|~ z{zl|vVk3zy4#;K#-u%MEVIr}jU%fskItK;tyz&b>MF?xu!Y4O4>wQYj$tgq)QXHz~mzqqM5RLcg$Y{D8V>L?*&d&EN4dV&?(PT|vM0JLSB81TiXglHm> ztUyr_R7+LZEVS8>;8@f+ERMWyom%3ui)r^maA6?Fg!sYIR1Hh~4-DODmGY`Xc7&>< zyuC_eSEZ)I2yrw8>!Jztrt0t*(u0MK0g}c;hCVflHBU}VjNsZ{gGNRcY0(<0IwTnY z+O$eV9FcF%?N&`XsAf|Xwlh45me{eM&s#22#OCPx4(pIcr_kTR$N`Ntk7(@VT6OK( zFU*mqs$7Z`Ez&hQ=)!aATT%}f$yxPQd3;6z*SBCL|JW?-b*!JBCqyt zMlK4w_OcmmuMnVEDAm76gm=HH0Y$Uy7qQ|lJ-uq zNOeVZkuoT8UcL8B@iuwWPn(Z>RR(So@vUyo4%@5D>M1#Kd(E`W!gq{w>o=_$VTMpc zI4|Uky%)`0@l7l2qHG0f>r>2lff=a7y}qJR3Y-+oo$gFZsI*8Y1Ig&jaqYZ@T?ODU z%#ZXKg#Ha^YK<<6Ks(gyEwQW`+Ac56u+ifd@i>Z&-U@_vBG37A5QmjyW+q8IBMEcg z{(4oJekhVn!%&CL(o(lv+k>*Q4W z3*fWn(71=?ISJo)7ARwB79XmyDvg;^qfPmac$ldJfNAaf;Jc$Iguk|a-ZhwH@T_ho zt!EGNqlxCR6WH-TVC|3}6Wy(vpqAn_Dwc??2PoV` z>YxE)JER@JZRySfK(hdJ4&;u_3`Jw(M$%$1(i2XvZ6NkCT|Rd9&y#eo;=&H74}2?7 zS0ln4$2cvcQk!qUU1f1%HoBFDHw~2AB1?0Ldt zDrCwmUcD-__{M{_0YfPk{)#g7=kj-N7f#WfdhEKe+ClSI1}?q9&)EGvv!%vm z?zw9j%jZ4r3i2}lHsE-Lcd34bbc?U;(Be1i!wXNcb6B-MThi)|3Lke|F!WlH?i>3< z-do+0gsoL9Sv(~*dws|3j9ngC4HZ6pi+5-5zWZfTnANeU4SO0Y6}%eSqi*eH;zk># zPo?-#jG-@8g-Q_v;A6EK50tLbt-y_Qc3SpmbX*Ju#+=S%0@cgnndlG zbo^M&CCT`;x|Ks*JCvNuB}erXzyZ;T5+&CvGO&4OPK3#Wiu(&;%i;4B0EK6{;?^W9 zoQ+<`re*hOSSV#|Hi>_|H}A!_!Iin8PLz-)qv61uZ2nhmx0^D#9~u$D-(MVMtgdIs11A7{uO~#Bc_?l zGkJ*;1f2W4-Wz*m_U}_UL7&O8os+4{7~(Rcu?pKznP5QWR%lMq#hW!YER>`)d5=G~ zq>|34d)ayD_4}EN`$|}gXZuw=KYVLDBO|}Ndi7vQYtF&`>x#T9O-25Xx;m3(-up7u zrk}SQT@Z3-r^lj)htu-LXN{O9y|4b`>a=$|wtutEyXdy7@t$L=%w;+3P2^dYx6<3)Ot1M>HN*zq4@7n_uEmmIjX3T)ZQ*0R~=K$X8 zHZbzLRo*=!+^Losajk~N8_@oR<4PlP?=s^e0$R=FF{-k#yX`}q`TVp<@8;Khe5<*0 z3j3wp2M$lX;7E=&pfa6{E@_0z#O;%$10@etb_IFa|`Ez&n95k;7$;(Dmom>44haH^F6-HG8= zsm7au-8k&$+7LTBcfG-&GQc1I4D=DQt0g(Yc%ze@AUaN@#7y zz)+ytjp!fqzY01-^%Z&Ihoxn@7j(}3PWQ9FwxZ|e^KGkr22v^FS4Gk5x~`eW#goZy zH#V5s=A;=n481$HS#-{;c{q`k8hG;5Pi4ObJ88a7>8ZJ=nG$cVb1Bo$TXu2vzN|31 zz;$uizfUi0KQPI;Vcd5US1+DZVUZa%F8%4d=MBq$(e^)o+!>y7Pq}bF$Nus;SK7e#PZu<$XUnw7b6(e&6bQHu3IF{{6p}rN*31unx{!XwU3benYDXNP2T* z!;F&-o~1Vg7^8pWga&iiFz@?!$M+O|a9r<)^W7T{tYUHuVxIn6?YeAdgKc zAE@Zb=V6E?%-T`|O~$G!-(1uM3c~$3Jwb6jvhm;P#jlsGgWqj8EUU+gK084n{Mw;j zwHK52l|tK@jq6$4ERV>6KDd?(_h8uC>S`XGAf&- zhqn9cV$BlTRrXua*bl*+KA=YaJVPsR${U%{LZzOnqC_&Z5}Lv`xKKjdD#1m*UMe>M z2qs)QmZ}q>8CXvcfp#@`8em{6^oCZ#os9-ciL5G^`BuQ^to0@~=D@Yq$j3$bN4)_q z=Efe-6qcJuNlQDrn_OmerWw%etZ|P1uL6>;?|U>M&Ut9r#QxL?P0x^q-O5%T)$w&5TRHmojjGAsQ`}ty*^MQFu8MVrZXZ{}Xm$6;8y>R%$&2BLCPDsKz z|HdPw6Q@*t_w%~)XS;F+mu@+>d6uQj=#wB0=8d>6%r3dfwSVX~?b&swnpG>W&0$c8 zzAM+~zUmMc{;+dr)}&Xff863dIo`P8ME+(;_RumP-IE4~+@$ZQKsl}yOegpDj zI}sc8FrrU^imHMMt8y``6nC*h7}|9b0|w{79rv*4YOY!g1+qPnXD*M5!Ywg?On3&p58 zfNPl;D=oq^L4Lqkv3)96Io6&jwg7+{zyqK>CT&-6t=QfK&|n3KH;Zz)*6LW+HVj?I zX+IiBPnzx0tbS%KPkvUGdUBba{+6A+YDkk5%apm&NvYFHF zdZVqIk53?%^k=f$=4Un?OWfODbh}?Rz`yw2mp9v{O<7Bu7EOQlW^(1UH!9xOzZIO( zPWJHs^4>D+*qeNI%wzlEMeFXl>BEloG%VbmVf)SUy!{bVTf(p0j>)*?nbLAR^Tdm5 z$Et$%UfWcbm%I0H)cmWt_Bx*j2g0T;S#s*>3Uv|RW@k*u-dgXJ_4Ts+N;!4issu-+ ztiJDPx#Vim+GV-C3At^LyFEPaM4UYLNBA~lX7N9@8$KAuCv#fEJ`X1*Cfzu8R}!s! z`1AL@^}WFh598s&$s-L8+H-;1J8AyUs^8{u=FAEy;9aW=|GK{EpL?&1rY+G%HPPH} zr+%&3MC#-NT6e`!N{!Cm7ldmIT7#d0-Ac49yIW0Eyddd}gNKDMYnw5a5Xl7Hr5J^4 z6+99X8FChRa7d=rHN7hf(fxpcP{zcd0c|E|OwCr$10J9jLtAvKr zIYo50I%IguC1K~gRd^&r#med60e!{w2K{paJ$cK&tPU_)8qk7A8PF!fj-U8$tQH;2 zI#$SIWi-LiPtk?D^7STHCXdSyEAG{p+o|vLBxo+?jbvsdD1Xw8dS4w%YF7jZMIc*& zE=ehrN>3XDq06~9J~1B_180s>Y?Y?!zR{u0If>~YdyEs>28NEYldg?5&_R>T61fRY z^&}kmIiO?)h`_|MWZF)hfoAE1${NrkazHb%=qqgq#K85d(TVZQhnhYWC0~@@s2?-- zPU#1u6aiqg$)~g{MNqWD;P@UGI!%{lW}ZvI%jnRqSnjiZ)T*ia_rk@j@CU+?pzj|$ zR!;XCak*Ypdt$oy$(32|4-aT)d;xIWDJF9FEeFcJG-A+V^N#07O^z!mm);*cCB5Q@f*y$_w3GG zVs2IXf4p1&9%Dt}&7vR9Mddie6>ZFFS*g1cGwI9c$w!Z8z4tqL@dD)?c|IIZUpI4( zYuD&H=Bk=}N8NDD`ZKiiE7i}ZtoyyTYfKhE+&aV?9f`4>4ef{9ntTz)gigUiC*594AYQ~-UhHq|7wp4hLS6ya3$B)$f#({={Tnv zZzE+XLC<34!0&n^qEQe2&%5w6=n0gk)y2jGxbqj{B2et~t;9Q4E%H^y)3HwQw7 zHM6cwscgLMEVWPDnwz&(l8!ZB4yVbX0gWQMz%zS zM5YWS?rHobRs3z0x>@O;vSZ-%yS3lVzWrBF=)i%NXT^&Y&JTVG*bvtsY+V<*OSZ5q zE6|Y0Wv&>}9i2Ee?6k?>uG{r?S=GnC-ETWyiQ*g!Pd!)W{q=p`ljEBN-n!>sZ(mBY zyWM`JFVZsfw$nAObQA>q+g>!HteQwYw6hhHWkOd#CeO#6r`7%?TuC?Y*ci>q7PqnrJ3f9M`y zA`nPIXS+&sjcArSHnma_ETK{&X9PBnkeGXj7g^vPcfBB@`2L#G)4Ez#CvNF3%bdTT^}*~XBwv!o>;BKzbE zpwvZkL8JN+RoSbXtqq8>QM46H1rW3|?R4TcaIT5@eKnaSP67g%1m&(R0O$EC!Ji9uy zGcFNjgtm+3YQaox17~?Zmt>r!YKs(G0JfBOuYchayQoy0R?)&(SeLqgB6nO%3$?EI z^uzv>!gEO|`p+WK>ObZVq`b`J-?r7ful0R!>umVz1M>!IeAoF7O5+zTU;HvH#{bNx z-v6R=(>z-8UoVjUU|0~nX7bIlz>p@%3Wvohw(YFrX%SID$4|eTxIZPY*?Yl*m%k4b zOzBv0esNo?FmGVSQ2yfUT@z~Lr;?s*a#?@o8o9ae=#FQWza;i{zuvv#Wx%;phj)IR zU-XVo6>!rVE7L0Dgbg!i>Uiy$e=qckY4?v>G4VhzZ>znX_dx3KeI$0>$*Zi8E@$pO`PX>z$gAHptn>@Yk>ZBJD> zKddN>2Sd@G=#_q`rNlBQG3spU;dZlAfi{ybhm}4N8NiV#fb-yk|BuJIM5m28ibu~A z6d0Jsshsv42~9LLdLmhIgn}xE=dyV%V(0_UUDJ zGOQEwrt2mA&Eed%`D z(#)m5mi!v}`F7IRtCn1zQgpm1Ou3Bu2L@;V#ahmk;qt5c$twll+1$!3ix{8dy3l7q z)py?Mm)xdt?T^mixwP@L^@PR;+kzLKsC2j%_V$1 zr=9w~#tiZuZVj9hJf$v{5JEI^f(0CbG{3`8mfk=ugh8aX4c5s)69*TOX-QQ_m{l|` zcDR)bWZD?l~A=2N!tiwbHyiVXOvRN(eoQSyDNGQ zbM3HQ&g90L5gn2NJFN&Y!}GOb6@vqZxri)eaR6jm12g{9*779iHC2U0T@s3#4ajhX zpImS9!%+cv5sfxUBQd)5XoPD=bc*$3s#3wh5{M`1Yo%EvMII)H4(_ji&F`vGF@wz@ z_YerTPu%1!QNd8>>2DFU#*akdcHoa9=2{y`9MBTSp(qYnScG3}N0G#)mRi=fdg>f;Vl{u$?wdaZAKdG8uPywHkXtl2<<<14 z`@Hi_>;LMTGx}z2-Lg=xFR!_uq#qYse~1(ui~J_c%Zd?h^WnqsA!c2RQ(bP;w-+0K zOZmVsyqq-SifZAtVWVW{KEtv-%?g{-QHsFAgebAx+212!y@%W2e*&aVOY10SVynpP zJujwRzqhZi_Q#EGb*G&F-u#k1>*-(9hWEKrVppoO#vQP2qLKg9zdv`>VBbjpwyVo1 z=sOXfn~Z)a5qV9W!8nxb-gVq5zNJ1dx4Y0L`D~O0r+T6%X2x@!C6R%Dd@C$2&UH8x zoffsDsJv^Z>Xj(a6!f`96_BbZS;R-lp^-`0B!u4}uK>CtgktEPp&c;r0oa3B@R>G}elsT?(o2CSbC7*v5Fu0P5go^p52{!S{HhLDC0F!l zSc%-J7MWuaHxR2*i&b9{()dcYQzIZ577CGWH0aY%VnlZ?JhW9U#YlAS5+Z-T0>VjC z=j>$@g#qCd+qvaAGWH55eJu^bBTQSYK;=@R6DvfXB+AQ?&ir)ywTZ2tJRJswo5h9+ z{CdHMV_7F$3zqYatI5K4MDgyfJpHMJ%NdNb&@ra%bi?nxulZ~S{_6DDGO=h&@q(ub zW4K|^hD=F#oSIwMRXXnM@ZViAOT$bh?Ip>l2l*?%<#9R0s{zfMfa{4_y>@t4lL;*l z=obdnpJUF=TbdGOFDrd*`nooQMs%M}^@ z!ls#L=M>vTV(K_ye5}PK)10Q-(Yk$%LpzA8q0&<4OLg}OIK%|+KtsURqJqLadH+Mz z^xm7{>#uHB>S_W8<0^jS^Ij?PK|6RhBpwot8W<`!6Q%-YX&#%W2Jqxa3op$(1Cghi zPzrHRUN;17y0nd`0%9+AkQTKyYash*a;|Q+Y(N%fNi;M9n|3x8+-d{-biWFf0{Lr3 z>><%xv75q*w9=2caNDvbK%YA?54i2kDiD3j2KIZ#L}JLD?&-6CuSXEk@&ivarE^%P zAQ>M9N-c>30Cqpw;q+kWQPl=0;uZ+j#BiwxRpUDY^2K3_9htFoMxhyUXP~zOy+>e9 zM+p4^6yjSzHhtLeQbuj$S&tLUiFt@{)6<$HB-BqPLnbfnV?Fzdm0%o z)glN~9wJhRPeACBOR+3KU@CX;#UIP4I3*N+IxKBeJr8- zv2RW*Y$pL{n0z+iH?t17H)6gI+v<+&{7|oY+9l02Qm4%dIis)@_{KV_f26r7G|onE zf1|JaSr>=5+=)}#vV6OB7eCa-T>gb+qIwP^;~CN_qoG_ zLYzq^)_DeE3VUO^+U1lTTg}g@+JEs{@H2GwZVHOgnW1vE4M7PjM#KbqWge*R1&C@X zllzo_6PFX;4fBruRQg`;#@16=vC?v#xC^CY{(7S&p#0i3YQR5G~0jP+5%*OgM%EScvGONeM3_Oh1b-#I(OqEB>3-mP3bE>|?+?mzEe z3w|Mzb6bwh9m@FHW|%b#}N?H_)3%u{nZY_QhXz{$gFi3y9EytC^@VrG82 z87&iq$(@FK^vlmWg(j%w$hTbD8GJSr!j`%Kqvu#!!!5>q$L19@BtTlLhWU2#HoeK>M{u68-W)SDbV7ie<8)lbI4Kil$xYOJpuum2ibhI(ZQQ{01-)lBoULW%UZC}y zZ(2R;#u>W@+l(9AXKm~ac9%Q-8C3gTPh)6{*tpd<#G9Q38mmc8v7C0$OvNV&T!EG}`&d+^Xri2*5Bfw&=2SkWb; zzfJO_LpKsN<>ivr-?E)#oypv_4A;BHLot|LCbF_EKnVqZHbD zfMw7D(@-V~*0fXpHY;^WQU|V;BESfr%wgJk3~~uoypTimBy~~*ZPlSN9IiV+@RQw| zgTg@?CVH|Uw=s-o2T_bwZX2hLpj;}F<`5#GK5w#)ORd%4s z7*-OdXrihd?s$7QM3?VVN}qPkK5@BeW1YP5>b1LxHQ#1-{W9CO?DfK<^nHJHlU2Rb zn=j4ZxbR&1gJV-D<30XSysL`Zko?BTb{-Vbe03UI?GBJHw=)_XE_lD4EY#n9@dI7-SeAG<8Q zholA5@9gI>`@Pkxv~TuZs~)an;3ID*e1CZ&>v^}z{kYJQr~ZLiE^Mc^=frnO+o=F#qJe_qkxqbZtRNKYY%VG6+((%GxfBw-dI;O+n*8WA z16ZHqbs_PE<{~*|l2*+#;y@0~3P5C3h_?5eOI+J6(&t5to|t_haK87p>4gB`N3hML zw5V|cP!Z@{L@(&t9SzMUe1Noh59>gci?znyg{0+YhTn{W;LQO5~$Q4bI(0&#Oel1aw zmW$(8d|vOF`sMM7v7URbq zQU)vyQR9LH z$Z<=qKTU|_6Mrw+Z}J}**hHfIZmsH%e6wzI`g?uYwmRCpzI#19r^k-v?~gltvwLw- zT!YBFug|HaZAI&!wEv=$;??!%ss~urlM~}VnOE60jyeH1Ec3d0-ohMY5~?kh*72X3 zQ~2S%O3^KoS?d=p`{raKgI}$@Wmxcfqzg>9sDC6Dr_Vii9@QV3ko^yS?s%Dt@7Wl? z#V3jO@wn&w-;bt-4$J&M=4_wi;O(kL^6k8*xjjdlM8(vgMbGE>UEX_rwk_MGiv4J( z#TgKnwEA@^mA74QOx(VFw9NykfjF~hnup!X%|l!#0yWdAV_mg_Cs%MhTAnbK&}Zh*fsCq zZUHHMDuqZd`yV-Mi>3Ozpjua*Sc_!#gx)Mc^cjJiS{f+5WriuqhaajiT|^AXas(t> z#x5940%tFXq!U_wXQmEqvgiOAgj0z(){HIYjt+9U-j#~;&ZOn!v~;|yyxn3QzoxuT zzf!l-z0qcUpjTx^uuKU7agP!qovo+wIr`UeHIPSUs2U$_5+V#$|Tfe?tq|Ny%Mftt*7WOE9XOC%>i#Zg-auXCjo)ss|Aw0D*_tP)DT$aHNl4;T z13y~pL!X*`9r{YnQtf&-85Vr;(OaGk%PeQDh(2}p@9&;0`E$PGe^Gb6eUj|(+Z<(g zwa28J*(5g-Zdx$oxoy#(j_s!8OCA5B#J&~mwOS0ioy5LhcG}6f*mp)rkH(l%tnAS- z9t#Y<%xxlOuzi}v___D=?-29ghN+j@=CyQ<-}guucXCu8-FxLk_;akgg)=j~t2p{< zq%gQ2`}aS%X%>5pBB=jPPkqCa&$4vRw-?mEZ2P@XSz=lxj;`!YDR1}r=HM#l=bL0R zFaEWqrlcsZG{}uTg;L90K|Fa!M$|{rbV(90o|*>(plGUzWKb{EaJ>U=Ew*B`sBArH zDFHPOL$ng!5agC1NZ^$l!Lk5B))}&O0$rkz;Zg?|l#nd$EDrur;Qp9Owh!!knaM&a zFaub7s4d$&n0hk{k8xN^_{jH*i;SnIBlNdca__Pp2ALroRS%%i~GGK zbS#0Kt-l6&^#b)+ardT{x=K5`+G+BekXlFvyI_n=50vV_GqJ5Ir5=(~9>6V1vad7< z?!icvd^t%s^yP})a>rfhE^&U2HC02NyiX^>-|L4UG}WojHWGcgdwmXfmp|-+GiaHX zB>g1K(o-E{eJY9+4Y^z^5O%b$`XFhwLUvjg&IYAJJBAxsYd0E9U&s6wNh{Ye((WGR z7dQ61onGisI9yV=@b0G-BN9_pqdR9JF;kQ9Wg^ROURe^?zdrWQ#Z7e&{^SnD?fDR0)buuX)#!_@68?qrNS1p!CA5>e;%R4> zU0e<$Y~LU8&n+uQ`!bp!)$h8dzQ*Ek0ejIO3Cez7;@N|X!(7K88f}h4dQ+QWe_LxE zmR~plx3TWISh)>9Dh^%~YChc`_F1}$yfr)r1q9tX%gLCh%@r1Q1)kacdf7hLWR2~) za{kTBM>kAcy{uY3Sgx+GS{=b=tv}uqcSuwo%KRJ+D`e{Z_dV_E}VQ4cFj2DQWZGrnrU-jj1O}R4X8*^j4~l%j5!%bQJVxH$tomJF@YP%QEfQSCOsTU`=ub&nqt~ zUZ?;wmXRBs-pE7{N`Y%c0gzL*hj{5Yp56cz5^p{TcV{9Ys7F<^i7}NL@-#N-jTQCJ z6uZE)Qez`R0WDYb-F1~~5ZRdk`f|pg=n|t4n6;k>ALIv!p%#fULwc|bxOyiayfQ$( z{aA8E*BA>*)f7rM*GehPirNN_dgbGGs=F=jOpb6#WE0QpD|{@W+0NO8jX=JDHeGDN z=UP=OUvBMA50br2?09+#t)UU>Zw~fPc~{?ECAzpqSFtpj2WG5b+&_0;FWP`ilG*D+ znWtTiEk^0o!V5>_zpqh_PSlOGb$o11u4){J@O=E(u4y86@Y+z(zkA~kdz}{jQ9itQ zAlv zHr5`1pGb>qyPcAs@bgw#UVm;ZeLHOOtNdu$ey%OY$;4OvVp6Brbk$dARX6TCL- zu3Sht(^cq_K^A4UHUsDN_V_}r^v~7JlM3GJALafnQOQ2+m0kGv=^jU$!l(OI%HFiq zedF@u=Frqbd%VJaU};yW3uap?|7LA03ST92@KNSXi!8}Kvi$7QZ#Jkmls}7$=U%@v zIpDW2QEKlA*#nXMKX#82t22VqiVR_DIcK1h0|#2`=KcMvYw zim@JvoN`s2u82gKBuARb-Ki&w**D?VEI4Z0z`Ce{D>^^NRO06$n=%8_PLNaV6w$(1 zU5LcrE;BmEGEtfhGLJhRkk2EjdHyE21P;6Z-0J`rQ*EklMjUs1TqfTh+Me_O#`oGY zC2x)xl#RA--SQf9Zmh;M1L6!lT3H+c;ZkNCW~a>pSX)pS{}41o3n|D%CTBgo5xW}G zJ^_H3E9OA##H=2R5bU#H6&I^qDiuFvcF7L)!NnA>VMu;2BrT?Mfjyz5zQYd>7IoP~ z+#$@0F3>F1%e#6|fXPSX*+$a1j16+4;6RR)V(XoP^@C1aX82#e2L$Y7xcCVXRyL)h zb>R9}?cKWaRd$vW!yi$8JGzYuI zt5sxrn0*>L;FRv{y5?PdS?OPO0+8TNnKR;6KZ zlPb^J6t>nz2%o#facUg@`Zq0#cq&Wk{Isd&)W=N7KqfzW*!Da)`mddwYj3|<@EVju znr>j~`oH|&1^t`0 zfJ1J*Js~8hmMJ$d4()nh%jB6sS$!N2r3SRy=t=aBaP19)f^rDwb9aJa4BY0c2F77s zpoF%QQ8K17_f_nV*C@tJ{;{YB=y3;&^EhO3i8>-W%@(=IZxJB)IO}hMgiV5iT_Hkl zcpxO6TvNwN^PlN^Ph5|?@b_XDZbvVKP~&y0cKYG;8OTXbJy_8*W;_7bfCF)pjb*^q z09#)IoM9%UtJstlvtuNL`;rCkjv5Io1VU|r0 z=bypN0rUQx|7o=0k4-^(f5BCJSLL**R$;2Wdt(dxmiy>NDaYipg;r>$E}5Ov>7;sk zB(cQB@nrY$|Ac;Sr_~HyaCOJ`d>CvY4&CC3nb^}W7`hjC!#3)h`P{UaqU=}Gri>n? zOsaagtZ>))iKc;HHvMvc-H-qF%|Eb0T@{@^r=!l6dFtuDP1$Zh|tPw7pATbi*y@F z{ObLe3Cf$bmbu@d{4w*?xv9U6tp6mTvn11FJ_pU(@O<7`Ui;N& zamyPi4psTx#VY$D+2s_aN3Y|!m!i0u$mSmp+~l|}s{6Qw1F;EzzgyaOZfV!cJ6Fe- ze=vTXeP7z~(^8LXt5?bK;84S3HKc*PC7ZPe0Vh7s-8zz6n6x_v)EYMCAhJQ zW}4<>dE;tbaeRKcT8Rp2_nQd^wd(q%B6dpR!SFvRp<87X%I=pU|J0OyiJNt3O5G>3 z+peF{r8tYCch2d%9$|M@f9;$*@1vn8?6NoKQ|GvG8gY*7Hc<7w)2<@arA8m4u_duF zg{#oEm*+XI8|!P(yf+t zHOCP~Og6JhhbM|elvDK+W=XVmd!--n;v!tJj4BWWvrhx>7Mx zy(Fj2L9i!4CpqVhQ7ER(B9pF(RdkrKl}BoeIpYaE@Z%gcySQ6FJLSUv=e$r_A-S{6 zieb_$GZpPqh($#{{-uUmAL7w3#ir2xLX z3cx=I2ptni3f?#{odQ!6bQo*>SCWX#Bm*s-p@6pFho&l|c)7=dGS`keSqp$9e!!3q z^50-Rzqu}J^e+oAXGu@;i(r6(_iP2>G00jW# zUl~aVtIAmxRxMHI2{1jhW>Bo>fgZ#w2GTkj)CHfY8|kkAfdvHxYqBXO|SQBI#L z+Zsi5V*5&tYXWk@;XW^6Cn#+-@zOH_Gos2WLz%D}|1OCyFG*|DZ=NUFFYy&pxb6`a zIUv?YWmv|7$T`?019v^?ikGLd9Sgz(CpD}KvSEjj@Wwn6e2Zfvqj72_AjjoZ{0BPb z6=n?EVuH#?t9WIz2WaPiT;Z}tRzAO${ zt=-BG=6Y$ppCinF=rW>2o@)IH)Xgiry!ATqmA4h3Ao5(&0=vRue6_CK)Qm5ixKwPi zzD~S9SU~LwrfwoM9UGpk_Iha8pZ&$@5jdZm{3FdeuL(Zc{->QOmWUL8)KmLS92o&- z`XxG(F=lF&8KHPSv0fY&C9f1}P_+GcX<^GN=H7$a_1du6d1{(j{lJ>3(_=5g|*t!-SV5qc@`@aUm zpL|pWuT(Z)mz_0F3r?D_aWm>O3hLHb6rG^&?PpjzK%#eVjS#V{?)kx66G@wrF$uI| zspYEZC9R51Y!B7oD6{W4W}<{Yk?R6Y2=n$E8kVNZD%bCzv5m?!v|39l-$) zwq_MAJ#em6p|@e#>(-BQc)n%c%8>ad&2{K!Bm&IX4Iw8D7B_=h#26Ucj$Jt7mib#i01n!5K#*`V{Q{zcivN}a)9to@5`l?=!>7-Ebu&}{ zBMsMP2H+oUz|swpg#1$Ce**wc;!; z&2?4b>!{$+eg{w8YCVG?yzAbi6Q#EBQz4!cP1WP5~5!`TA$eZ;xT(y@zwFgs(dSNH}@J1{oT%jQ{r5eiH@V7JTTVXxnB?dxV14`Xn6g($s%6Y#I~b4kfY@dh{JKlx)R^>3TL)8RAN66V>PN|O7oJA(q&A{HAalbJmP zx5o-L4tT9e1;Sf{oi73wRP}&C<|;kM<>YCDn_;*8o;V?@DTWg*gx*a$%4Qz9_;U$; zM$r}MA%G4*)U{cp6Y7_QodzsTqz%gN+7!TAm`A(El0Z@7mE%4WM&~P(P@_p;$o|U4 z7kw8F|1Oh?>%c71F}Ki5@SLwOIl?ufSu-V{!C>s}&&)b&K1Ng}(9VGvzV?q^c3Avx z6>YD6`rfHe=P>f|Wc5DU!;+Hk;(dSVFv)WJH*8!-;m!`0KXlc^F1)?j z6!tjVhTwVuA$-!qK=#YAX?o;daL8*?K<(H-~O8^1G2@N8&nG%ka})nZr7De&q;%uafVpwy#{>eM46?+vpdSu zuI@QuXJ%ra1d0rlI}Gj&!9~jbH|^4F339cjXjx^99lQ2!9RGT0jYfV7g?Dd!N8^s{ zCRy{Hj%tj0=%?8khT|&-Ivk7I%`X1*A2dh#9=kRJr9%{Uap%gffKoE>0Bxs^3K!DF z6)$v02(Zl#_?;0KaTl3c+t%(#SbBn0(~ex#uZel3-v2>N@cO2X3s}g~zxbFAZr746Pthg>G9jR(wknf^Xs*S356#6l0KmLzM z3wLFwFW14P)v3RZ>L=LK3JJDZp>^vQ>TL3o?V1yNPIm9&pI zX!SZnV|$dHPG!=@&F`A!bI$2L_K*~?Y$jMrWW+N_zSryi#SxJy3m=;)gEBVGy&vUg z*LdZ0`S~$2g$3${dK+`g>sn^qRQ{4KtEk=)y7xTSSQ~gzTGLmLDG53!py!6p4Lv@2 zJMqMO$2nv3snnMuB$r#nx*iRjN^4MlJ?EOl(A z{Y*-2s%WN7uMHMr=rB*4=Y&h47y>7*BNHWF`8A7QH9pNL>3jEac7_b-0J-tW6zzN28B?f5)c;ZZC^zr&HF0g7Uu?UwI=#qG`*#&uxmT1U0Kg;tM5+aeol$>nL@Qi{^xAFQ2WwF zN>Dau!+xWe*$#X9{1UKhjP>I0wy+tC#md6(QNt16!hcFTmeVldBZcfbf$gGb=O6>v z?HO($j}8g114pQiECd8Q1c)e6m0++bZ&d=4CU>dviL#o=N_c!oMqY#1`8!{JIq^S8 zsB>^plqg?N#)QJJGVC9Sc(#jt#nlIu`KP^$0cZ!dSyia7ZjBD6!#8w$lSR9Xn?10U zyOSwIl=~J$wH}SL!Bwo>X6u0kn`wJiy^44lURRk7B)!`(ehLjO+qFr*n+c_ktzV~i zrY$=Eo%*ukL|s{XQbptLri>p{r4YY$>c_(>t`hmB7g3nBwIbrI?{Vi@s+%!0#qV9W zUyUYiNii9-gltha{`9?aEO@MZ*3XdTwk^e(M~?O4^dRAPqf0bhY8qlaRn9xm)zf;E z_nab#7b~|R70|_?SwNX3e$s%KD9(A+Cf4widKoG$xl9_%q0PjRMa@;9dB#Dwmc=&X z_jv0y9Bh>-kseB~)@q(7K0hzSRQ=U5>&%s~OoUzgzB!O|!W;F>!bb|u-zYt0!lT1K z#Kt8^k`t&`M1F$`xfp1H8r%K zd(MHO{Txekj{X@C!&uL@3vm0foN2lxXTNBY__v@~H{*{J-3njSVIhiR+lLi|{wTF` zI*0zPwNNEHD?C{cBa)g|r#a1k-F(IP>h56z&{mWNZkzpj6(j`fFFB@rh77+kR&A57 zZR*gvC^R%Au;OOifz06_=&CKH-Uie*tA)P!83xQSC^KFiaR+&bm*dAU3RFlyml}Rl zA2TdRk8@wu&}ep%F3`-L*N67fhi-McY|5GTZWj-0Zk}t}YSu4^ic+lNlMUr!6l_J2 zGsrzf7Bd|f!WZZF(&(h6!qL3(pgto^ej=0hEV|9TtDYF)HkL%(xHysH{+UVh+0d8c zJy#noVOcJ&^YQukFfyVkAWnSR`+0PkGn=I!sStQPbI6YDA#^ZMdc#YE?AO!ao(o{0 zLMO#f@G@#2^?mDtkn#L*`#6!oq|mo~zYwmy!A3*;FqXU-fsQolAvm4gU0k}Z!sLQM ziqorP#vV5DJos%jPJ7zThUJu2TowUYxs!G{CUb!J5bc%X z_jIK<8*l(XO#AKk3ON8u9Vq~Ife@Bf(zK6Xa|OuqFcK@X$FrPCBMLuy5DR#l%1DJD z;-T+=prw;nhrWaby(9%S{BCw6C?rET36gL$m}Kz+g9+hm$bHr~lp0pp1*is4EJ-gj zFS1K36|xdFQtZr2Cu0vSFy}&$bU;JPz3OnEos<-A#LF8KX`9+BPnJ;4arv%60j!nL z3JhiG?^VW(^on{KBj9Tav2EAA!NT+qPPFGO-Avi0S2(qLFdGA9m|F2NKwz%nZ^5uS zj16B~2(9*24)|jCc+sRJCyfrXI|IN(Le_g83HSoKtL1Y9h(`B571?^O%{<9$mb_d) zrHmU%Aa5};o5H7Nc-~W)+@(jZNWK2F9<|NdnR@Hk$Vu8m?i}&?;`Np&3!D?P_~Y?K z@z)$cRylXQbtt`4cckL^lK4@AB(mcue!$%0dlZxFZT6-?Gx6I1b#-peEqPRNOj{gN z!LJCO_g1H4isVbInJ}MhJCu@YATkO%=ag@wW{1i$ti_hLv+BOb{-B-93UtAK=X=aB zQlG^!HIK9xwwipAo)}oe!KuwEq@6Fz8Yp+ijHG^(n4>t%^of?`On>1n#C^E?p}R5x zdvhqa>rlpK$8_#W58O@V)q#&|5wubk^@bIeS47?s2px}xbu$ZtP>}#Xi=1I7IwVjp z&_gpTlT_?u7|telyszvjc1X3?k+J_^p-#i9hP`q;%b&?AEjrswic;9Fz*=4skS>4o zen^?tM6$=JmiK1`dJC$C5<%w_{#N}IV*uuf=o{olt>Rf~@xl{h?CsmGG@O4|iXSs< ziuT=W@(|5GzCwmW2gbx=uXi~TmP=M%EYHK19Q}=q`0J@i+qvqFF<$4hpag~Sv@>>R zPVh^7wjtjw+#$dM^mG0p`R2So)8>0mjY)ezHo)pU&AzFVeCwn^#uM+5ZHnEt0*&qCnkxbxXKb0I z{N#I>jL>U{Ynep1lX?=!ezpP?Ospg)OXQ6VKKPHR!%&Y_DcvZXjSP-qFhC{K2G?pc zzaSn!*Q23V7w|;Fr`|`bP4e6cQKVpao~XRMhPNEaTN{xTSHTT9!?C2D;q~IbK~W>) zD_%N))r`R(t-O}vlL9=Vp{T=@EGBTM6ewsj2HK4Mf%8GWAjk8-3grpVfqA6%YruLJ z<4^@RKCA6Vvie`xl)S^t;r0YGa~gIuDd%*@UircUIwhLLxCE4=zc-Y!!>9hnUm~Ga z!Oxmz-i0(8yV~wf5qH}ERNFtcRU$9HolUjIf0yqg94m_bA?0(z8;K39mQK+&wLN7| zlZH1Ve$sRf$5kyoaGVwxm3`owvtE{jR{LO+DZd8hX7?U6`lVC4sAcxFq-y*OfB%kL zhBeJFEFWg5V#hwb3tsm{n#O|(TPjIy2jd>}jR-N3`AV)&X7?Fng`_M?V1MzMZ2R(o z5J8s)yzuaq7j4F^+R?Od2gdp!8GpYa(j$18c2^|HNXssl@sXok!@KBI%te)m-TOaP zvbJvZc=*Bdc$IyTf3UaNyB~iOU?zo)g9UMk^Mvm0JKPBMZIDfPedlrWs&mE-HahBhTm6I zSM@T8D&G+Z?TZNDDyS>vs`m3l+Z`AK?(E%U&A9WO@1>>#V-lf4lzfr?Qd&aKwJ8(y z`SZZPzAH*9hoQ?7cB1~BOcOXRKG}4yKBuYMpzoPs(UL!F2%6@nbw`qW;8JoJ$;uh zuc5u&?|P*56$F^>)eFidc@f9jb6E!Xnq)in#S!eH zu%l5c9vF0i{1J$RJXrySm?|%X5Kgu0k-J2t{n2~>lv#>j%PbKj@NweCKn`rG}O`^ zW&$p$)EayRFlLNe+-QN^Ibnq{%i#H9#l=RS8lCHfUv;F4ku#)mDxe{OoWwiYoFZjt;o`UD<_xyJ3y}#o`#mSDrD=Ht8Wlv>oN!>KRpF8TW zKdozM!E`sOSbOrw5Ei`|TSiI=|&XXskjIt49OoCb{4GH=I7X@h@N1^8CUYfCTHI+;y- z)d7x<^)8KwxcLY&82EQu{p`K!SZfk^IDrRcl`)-Ai9;)rxi-inX^8SsEDDmGB0&F| zx!FK=l$sUldvHJfMM!PL+g3PAp=Wg~61Ybo_p1N^lX>I;KHHZJ|J)tni;z--dWk4E z41kg#IxA0Vh`_ZUlZ$`P4*ETnvi{&z5?AG_OY=iMX!srb#B+jHmSfpt_5uQCH1pm)X#jL=U;dGsC&IKLu;1 zFYJxJP=(D7sd<0sY4~JKR>N$Aj~rBKgm?#_+xkQTW!clB6q-3a6^yRGaj% zt!9arbv6x5R15?xSnO+8W&T+W{c-0}fgTktw?gIIq2v&sX;efqB_%-kkgyCac0@2P zW#&8eX9=Nw10E4OBf7PxqbgaZbB=lM)3r_8dj~TrS^9gMh4^mo0#O7&pjOp6;G4Cj z71idS0oK}>D_;WGruyh1S{Fn{5FPW>9rM0KgBSozMcK^0R4PHjHvvPnv>^z8+}4^0+pwsxHVFi4l$h=oU({iOtoK6}uq}R~c5+ z_|X1>2)3LXj{@`-I41!d%eWwTQ4~b^(E~rZBpAT|n*jn+Cj)m^+W{9QgEH-okM#ru z-8_EMNcLTjj>po@p)5fUurGGro!(swX@ErY1#m#Z1h>pPkv>e^@D0F97Nim>G;#sg zBK+5V1&Vy;b5DE@)Vlz}YmUSaK)NC%4gEPUjitd3Ji8UziUZyf=r=w*4+UAc*|8xP z_A}leSAt(y=w_fl5LH$6=6UA|{Vb6lJQuo#;|EfRvfHBq<0Pd%{wl*3J60BGt$E}r zOK0n^FQVk?9_f(_Q-eSZbWxnaD=t;0otTQjx8y(i0th8-&_o*WcJ#}g9=O{30ztM35}+1K^}xwtqaQLHo_H( zFN7E=c-a9M7DWPh5VLpT92%=5eFj|j3;VJ|3Sskp_9)1{>oGaJBjQpC&$SC-vQa!^ zE0oh&1{9*{KDHc*>jFtcXVF?R<>5M>cN%YM#mbhMzjA!yd(4!`A?K&6u z-+Xd>*nS|_=1$T;7lD@ld%7O=1pNiTA<_l!*imi9beJ`DBfgay4FKxT(b%}kTq%U* zQQ8RiK#%Ju8PN&YiUGjZ>H z{$XK=i-OS-YDOM_Jr(H4=JE=GBc1|Gb-y2Zz<7ka4v5#@IPhObQb3dkbSMC8Rv*0Q z{5$9Rdri-4c-0Z`25<~hh#OJfH~`+M29`|NQyzFjMH|1T*G)h7&ae-S92)crD>VVpiA@7%(MQ<@KI-T%mHxJ+{Qt8D=eE@bJeh&Dm4#qm-e3<1WrIbq zm?x{s0NZF%z~(hz9YCpcgQLK)wEV!@Esp}iz%THBKlr^NjRc+;m0&$PK#d0MAb>@s i^twS8|9cC){`m+3KgrnFr`gO+rB3E2e+7?3-~K<-_)KvC literal 0 HcmV?d00001 diff --git a/02_卡人(水)/水桥_平台对接/飞书管理/参考资料/卡若的飞书日志_说明手册.md b/02_卡人(水)/水桥_平台对接/飞书管理/参考资料/卡若的飞书日志_说明手册.md index e0aa661f..f9f447f1 100644 --- a/02_卡人(水)/水桥_平台对接/飞书管理/参考资料/卡若的飞书日志_说明手册.md +++ b/02_卡人(水)/水桥_平台对接/飞书管理/参考资料/卡若的飞书日志_说明手册.md @@ -71,6 +71,17 @@ python3 "/Users/karuo/Documents/个人/卡若AI/02_卡人(水)/水桥_平台 python3 "/Users/karuo/Documents/个人/卡若AI/02_卡人(水)/水桥_平台对接/飞书管理/脚本/karuo_feishu_log.py" --interactive ``` +### 4.4 3 月 1 日专用(写入 3 月文档 + 配图) + +- 3 月文档需单独配置:在飞书复制「2026年2月 突破执行」为「2026年3月 (突破执行)」后,从地址栏复制 wiki/ 后的 node token,执行:`export FEISHU_MARCH_WIKI_TOKEN=复制的token` +- 写入 3 月 1 日日志(继承 2 月 TNTWF 结构、不含 2 月内容)并尝试插入配图: + +```bash +python3 "/Users/karuo/Documents/个人/卡若AI/02_卡人(水)/水桥_平台对接/飞书管理/脚本/write_0301_feishu_log.py" [--image /path/to/image.png] [--overwrite] +``` + +- 若 API 插入图片报错,可将 `参考资料/3月1日日志配图.png` 手动拖入飞书 3 月文档中 3 月 1 日段落处。 + --- ## 5. 参数说明 diff --git a/02_卡人(水)/水桥_平台对接/飞书管理/脚本/.feishu_tokens.json b/02_卡人(水)/水桥_平台对接/飞书管理/脚本/.feishu_tokens.json index c86ee980..a5fd0b43 100644 --- a/02_卡人(水)/水桥_平台对接/飞书管理/脚本/.feishu_tokens.json +++ b/02_卡人(水)/水桥_平台对接/飞书管理/脚本/.feishu_tokens.json @@ -1,6 +1,6 @@ { - "access_token": "u-7VelB5t1J6xrwEh5fd0Ftwl5mWoBk1iPMUaaYRw00BPi", - "refresh_token": "ur-6MS.YzNGd5KoE3SUs_5r3ul5kqU5k1WrWEaaEBM00wSj", + "access_token": "u-76K_MmgJZ608iRfu0MnVMRl5mWiBk1oNjoaaUMA00BPm", + "refresh_token": "ur-74mu20jQNcao4XpFppUfuel5mgUBk1WXjEaaZAA00wy3", "name": "飞书用户", - "auth_time": "2026-02-28T19:27:39.322083" + "auth_time": "2026-03-02T00:24:03.226421" } \ No newline at end of file diff --git a/02_卡人(水)/水桥_平台对接/飞书管理/脚本/auto_log.py b/02_卡人(水)/水桥_平台对接/飞书管理/脚本/auto_log.py index 6fc1ef76..4a19a422 100644 --- a/02_卡人(水)/水桥_平台对接/飞书管理/脚本/auto_log.py +++ b/02_卡人(水)/水桥_平台对接/飞书管理/脚本/auto_log.py @@ -25,6 +25,7 @@ CONFIG = { 'MONTH_WIKI_TOKENS': { 1: 'JZiiwxEjHiRxouk8hSPcqBn6nrd', # 2026年1月 运营团队启动 2: 'Jn2EwXP2OiTujNkAbNCcDcM7nRA', # 2026年2月 (突破执行) + 3: os.environ.get('FEISHU_MARCH_WIKI_TOKEN') or '', # 2026年3月(突破执行),需在飞书复制2月文档后填 token }, 'SERVICE_PORT': 5050, 'TOKEN_FILE': os.path.join(os.path.dirname(__file__), '.feishu_tokens.json') @@ -346,13 +347,14 @@ def write_log(token, date_str=None, tasks=None, wiki_token=None, overwrite=False print(f"✅ {date_str} 日志已存在,无需重复写入(可用 --overwrite 覆盖)") return True - # 找插入位置(倒序:插入到"本月最重要的任务"标题后) - insert_index = 1 - for i, block in enumerate(blocks): - if block.get('parent_id') == doc_id and 'heading2' in block: + # 找插入位置:有「本月最重要的任务」则插在其后,否则插在文档开头(index=0),避免新/空文档 index=1 报 invalid param + root_blocks = [b for b in blocks if b.get('parent_id') == doc_id] + insert_index = 0 + for i, block in enumerate(root_blocks): + if 'heading2' in block: for el in block['heading2'].get('elements', []): if 'text_run' in el and '本月最重要的任务' in el['text_run'].get('content', ''): - insert_index = i + 1 # 插入到标题后 + insert_index = i + 1 break # 写入(倒序:新日期在上) diff --git a/02_卡人(水)/水桥_平台对接/飞书管理/脚本/write_0301_feishu_log.py b/02_卡人(水)/水桥_平台对接/飞书管理/脚本/write_0301_feishu_log.py new file mode 100644 index 00000000..3cdd0336 --- /dev/null +++ b/02_卡人(水)/水桥_平台对接/飞书管理/脚本/write_0301_feishu_log.py @@ -0,0 +1,236 @@ +#!/usr/bin/env python3 +""" +写入 3月1日 飞书日志到 3月 文档(继承 2 月结构,不含 2 月内容),并插入指定图片。 +- 使用 3 月文档 token:CONFIG['MONTH_WIKI_TOKENS'][3] 或环境变量 FEISHU_MARCH_WIKI_TOKEN +- 若未配置 3 月 token,会尝试在 2 月文档同父节点下创建「2026年3月 (突破执行)」;失败则提示在飞书复制 2 月文档后设置 token +- 图片插入在 3月1日 标题+高亮块之后 + +用法: + export FEISHU_MARCH_WIKI_TOKEN=你的3月文档node_token # 在飞书复制 2 月文档为 3 月后,从地址栏复制 + python3 write_0301_feishu_log.py [--image /path/to/image.png] +""" +import os +import sys +import requests +from pathlib import Path + +SCRIPT_DIR = Path(__file__).resolve().parent +sys.path.insert(0, str(SCRIPT_DIR)) + +from auto_log import ( + get_token_silent, + write_log, + build_blocks, + open_result, + resolve_wiki_token_for_date, + CONFIG, +) + +# 默认图片:对话中提供的图片(可被 --image 覆盖);备选为飞书管理目录下 +DEFAULT_IMAGE = Path("/Users/karuo/.cursor/projects/Users-karuo-Documents-AI/assets/_____2025-08-28_224559_607-b4d3b3c1-6663-4ed6-9ee7-a1fa4426031e.png") +FALLBACK_IMAGE = SCRIPT_DIR.parent / "今日日志配图.png" + +DATE_0301 = "3月1日" + + +def _get_march_wiki_token(): + """获取 3 月文档 wiki token;若为空则尝试创建或提示用户。""" + raw = (CONFIG.get("MONTH_WIKI_TOKENS") or {}).get(3) or os.environ.get("FEISHU_MARCH_WIKI_TOKEN") or "" + token = (raw or "").strip() + if token: + return token + # 尝试在 2 月同父下创建 3 月文档 + feb_token = (CONFIG.get("MONTH_WIKI_TOKENS") or {}).get(2) + if not feb_token: + return None + try: + from feishu_publish_blocks_with_images import create_node + token = get_token_silent() + if not token: + return None + headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"} + r = requests.get( + f"https://open.feishu.cn/open-apis/wiki/v2/spaces/get_node?token={feb_token}", + headers=headers, timeout=30, + ) + j = r.json() + if j.get("code") != 0: + return None + node = j.get("data", {}).get("node", {}) + parent = node.get("parent_node_token") + if not parent: + return None + doc_token, node_token = create_node(parent, "2026年3月 (突破执行)", headers) + # 新建文档用 node_token 作为 wiki 入口 + return node_token + except Exception: + return None + + +def build_tasks_0301(): + """3月1日任务:继承 2 月 TNTWF 结构,内容为 3 月首日(昨日=2月28日,本月未完成并入 3 月)。""" + return [ + { + "person": "卡若", + "events": ["昨日完成度", "本月未完成并入3月", "今日核心"], + "quadrant": "重要紧急", + "t_targets": [ + "昨日2月28日:一人公司5%、玩值电竞25%、飞书日志100%", + "本月未完成并入3月:一人公司、玩值电竞、卡若AI 4项优化、20条Soul+8点朋友圈", + "本月目标约 12%,距最终目标差 88%", + "今日核心:每天20条Soul视频 + 20:00发1条朋友圈", + ], + "n_process": [ + "【昨日】2月28日完成度已更新;2月未完成项并入3月首日", + "【复盘】从聊天记录与文档统一整理;3月文档独立于2月", + "【3月突破执行】未完成项自3月1日起持续迭代至100%", + ], + "t_thoughts": [ + "3月日志写在3月文档,不写2月;昨日与本月完成度、未完成项均写入当日", + ], + "w_work": ["一人公司", "玩值电竞", "卡若AI优化", "20条Soul视频", "20:00发1条朋友圈", "飞书日志"], + "f_feedback": [ + "昨日完成度已写入 ✅", + "本月未完成已并入3月1日 🔄", + "本月/最终 12% / 100%,差 88%", + "今日核心→20条Soul+8点朋友圈 🔄", + ], + } + ] + + +def upload_image_to_feishu(token: str, doc_token: str, image_path: Path) -> str | None: + """上传图片到 docx,返回 file_token。""" + if not image_path.exists(): + print(f"⚠️ 图片不存在: {image_path}") + return None + size = image_path.stat().st_size + if size > 20 * 1024 * 1024: + print("⚠️ 图片超过 20MB") + return None + url = "https://open.feishu.cn/open-apis/drive/v1/medias/upload_all" + headers = {"Authorization": f"Bearer {token}"} + with open(image_path, "rb") as f: + files = { + "file_name": (None, image_path.name), + "parent_type": (None, "docx_image"), + "parent_node": (None, doc_token), + "size": (None, str(size)), + "file": (image_path.name, f, "image/png"), + } + r = requests.post(url, headers=headers, files=files, timeout=60) + data = r.json() + if data.get("code") == 0: + return data.get("data", {}).get("file_token") + print(f"⚠️ 上传失败: {data.get('msg')}") + return None + + +def insert_image_block(token: str, doc_token: str, file_token: str, filename: str, after_index: int) -> bool: + """在文档指定位置插入图片块。先试 gallery(18),再试 file(12) 两种字段风格。""" + url = f"https://open.feishu.cn/open-apis/docx/v1/documents/{doc_token}/blocks/{doc_token}/children" + headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"} + + # 1) 先试 gallery 块(单图) + for payload in [ + {"block_type": 18, "gallery": {"image_list": [{"file_token": file_token}], "gallery_style": {"align": "center"}}}, + {"block_type": 18, "gallery": {"imageList": [{"fileToken": file_token}], "galleryStyle": {"align": "center"}}}, + ]: + r = requests.post(url, headers=headers, json={"children": [payload], "index": after_index}, timeout=30) + if r.json().get("code") == 0: + return True + + # 2) 再试 file 块 + for block in [ + {"block_type": 12, "file": {"file_token": file_token, "view_type": "inline", "file_name": filename}}, + {"block_type": 12, "file": {"fileToken": file_token, "viewType": "inline", "fileName": filename}}, + ]: + r = requests.post(url, headers=headers, json={"children": [block], "index": after_index}, timeout=30) + if r.json().get("code") == 0: + return True + print(f"⚠️ 插入图片块失败: {r.json().get('msg')}") + return False + + +def main(): + import argparse + parser = argparse.ArgumentParser(description="写入3月1日飞书日志并插入图片") + parser.add_argument("--image", type=Path, default=DEFAULT_IMAGE, help="要插入的图片路径") + parser.add_argument("--overwrite", action="store_true", help="覆盖已有3月1日日志") + args = parser.parse_args() + + token = get_token_silent() + if not token: + print("❌ 无法获取飞书 Token") + sys.exit(1) + + march_token = _get_march_wiki_token() + if not march_token: + print("❌ 未配置 3 月文档。请先在飞书复制「2026年2月 突破执行」为「2026年3月 (突破执行)」") + print(" 在浏览器地址栏复制 wiki/ 后面的 node token,然后执行:") + print(" export FEISHU_MARCH_WIKI_TOKEN=复制的token") + sys.exit(1) + + print("=" * 50) + print(f"📝 写入 {DATE_0301} 飞书日志(3月文档)" + (" [覆盖]" if args.overwrite else "")) + print("=" * 50) + + tasks = build_tasks_0301() + ok = write_log(token, DATE_0301, tasks, march_token, overwrite=args.overwrite) + if not ok: + print("❌ 写入失败") + sys.exit(1) + + # 获取 doc_id(obj_token)用于上传图片与插入 + headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"} + r = requests.get( + f"https://open.feishu.cn/open-apis/wiki/v2/spaces/get_node?token={march_token}", + headers=headers, timeout=30, + ) + if r.json().get("code") != 0: + print("⚠️ 获取文档信息失败,跳过图片插入") + open_result(march_token) + sys.exit(0) + doc_token = r.json()["data"]["node"]["obj_token"] + + # 在「3月1日」标题+高亮块之后插入图片(与 write_today_log_with_image 一致:insert_index+2) + bl = requests.get( + f"https://open.feishu.cn/open-apis/docx/v1/documents/{doc_token}/blocks", + headers=headers, params={"page_size": 500}, timeout=30, + ).json() + items = bl.get("data", {}).get("items", []) + root = [b for b in items if b.get("parent_id") == doc_token] + + def text_of(b): + for k in ("heading4", "text", "todo"): + if k in b: + return "".join( + e.get("text_run", {}).get("content", "") for e in b.get(k, {}).get("elements", []) + ).strip() + return "" + + idx = None + for i, b in enumerate(root): + if DATE_0301 in text_of(b): + idx = i + break + if idx is not None: + image_index = idx + 2 + img_path = args.image if args.image.exists() else FALLBACK_IMAGE + if img_path.exists(): + file_token = upload_image_to_feishu(token, doc_token, img_path) + if file_token and insert_image_block(token, doc_token, file_token, img_path.name, image_index): + print("✅ 图片已插入到 3月1日 日志中") + else: + print("⚠️ 图片未插入,可手动拖入飞书文档") + else: + print(f"⚠️ 未找到图片(已试 {args.image} 与 {FALLBACK_IMAGE}),跳过插入") + else: + print("⚠️ 未找到 3月1日 块,跳过图片插入") + + open_result(march_token) + print(f"✅ {DATE_0301} 飞书日志已写入(3月文档)") + + +if __name__ == "__main__": + main() diff --git a/运营中枢/工作台/gitea_push_log.md b/运营中枢/工作台/gitea_push_log.md index 3b57b1e7..c1925ded 100644 --- a/运营中枢/工作台/gitea_push_log.md +++ b/运营中枢/工作台/gitea_push_log.md @@ -190,3 +190,4 @@ | 2026-03-01 16:48:22 | 🔄 卡若AI 同步 2026-03-01 16:48 | 更新:运营中枢工作台 | 排除 >20MB: 14 个 | | 2026-03-01 22:34:25 | 🔄 卡若AI 同步 2026-03-01 22:34 | 更新:运营中枢参考资料、运营中枢工作台 | 排除 >20MB: 14 个 | | 2026-03-01 23:41:32 | 🔄 卡若AI 同步 2026-03-01 23:41 | 更新:水桥平台对接、卡木、运营中枢工作台 | 排除 >20MB: 14 个 | +| 2026-03-02 00:14:40 | 🔄 卡若AI 同步 2026-03-02 00:14 | 更新:卡木、运营中枢工作台 | 排除 >20MB: 14 个 | diff --git a/运营中枢/工作台/代码管理.md b/运营中枢/工作台/代码管理.md index 6d76aa94..1e23f500 100644 --- a/运营中枢/工作台/代码管理.md +++ b/运营中枢/工作台/代码管理.md @@ -193,3 +193,4 @@ | 2026-03-01 16:48:22 | 成功 | 成功 | 🔄 卡若AI 同步 2026-03-01 16:48 | 更新:运营中枢工作台 | 排除 >20MB: 14 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) | | 2026-03-01 22:34:25 | 成功 | 成功 | 🔄 卡若AI 同步 2026-03-01 22:34 | 更新:运营中枢参考资料、运营中枢工作台 | 排除 >20MB: 14 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) | | 2026-03-01 23:41:32 | 成功 | 成功 | 🔄 卡若AI 同步 2026-03-01 23:41 | 更新:水桥平台对接、卡木、运营中枢工作台 | 排除 >20MB: 14 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) | +| 2026-03-02 00:14:40 | 成功 | 成功 | 🔄 卡若AI 同步 2026-03-02 00:14 | 更新:卡木、运营中枢工作台 | 排除 >20MB: 14 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |