From 59966a2f17d9337f636b693d01e69b70992399a8 Mon Sep 17 00:00:00 2001 From: itqop Date: Fri, 19 Dec 2025 14:14:51 +0300 Subject: [PATCH] fixes bugs --- bot/__pycache__/main.cpython-312.pyc | Bin 0 -> 4086 bytes bot/core/__pycache__/bot.cpython-312.pyc | Bin 0 -> 2588 bytes .../__pycache__/middlewares.cpython-312.pyc | Bin 0 -> 3129 bytes .../__pycache__/scheduler.cpython-312.pyc | Bin 0 -> 6054 bytes bot/core/scheduler.py | 18 ++++++++++++------ bot/db/operations.py | 3 +++ .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 154 bytes .../__pycache__/callbacks.cpython-312.pyc | Bin 0 -> 11491 bytes .../__pycache__/common.cpython-312.pyc | Bin 0 -> 5085 bytes .../__pycache__/errors.cpython-312.pyc | Bin 0 -> 2346 bytes .../reminders_create.cpython-312.pyc | Bin 0 -> 11093 bytes .../reminders_manage.cpython-312.pyc | Bin 0 -> 20972 bytes bot/main.py | 17 +++++++++++++---- bot/utils/validators.py | 4 ++-- 14 files changed, 30 insertions(+), 12 deletions(-) create mode 100644 bot/__pycache__/main.cpython-312.pyc create mode 100644 bot/core/__pycache__/bot.cpython-312.pyc create mode 100644 bot/core/__pycache__/middlewares.cpython-312.pyc create mode 100644 bot/core/__pycache__/scheduler.cpython-312.pyc create mode 100644 bot/handlers/__pycache__/__init__.cpython-312.pyc create mode 100644 bot/handlers/__pycache__/callbacks.cpython-312.pyc create mode 100644 bot/handlers/__pycache__/common.cpython-312.pyc create mode 100644 bot/handlers/__pycache__/errors.cpython-312.pyc create mode 100644 bot/handlers/__pycache__/reminders_create.cpython-312.pyc create mode 100644 bot/handlers/__pycache__/reminders_manage.cpython-312.pyc diff --git a/bot/__pycache__/main.cpython-312.pyc b/bot/__pycache__/main.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0007366d2124dfdc8d0d07e29e0e34f82894aea7 GIT binary patch literal 4086 zcmcInO>7&-6`t82a{06Tk*FW)cO}`fDA`of*p3mTNoC23T~|UJxd#&gwiI_QQzE&< z>@v1gtB~!qmSY#TQ6LV`2GF6G!YNSnRJ4b}mTtXBkzA=80V$9aZEu9-qK?}`-we4V z<49>Q9dKvfym>SGX5V|?d;Ehedl9su{U_2}9)v!l6Q>DfV&^@K&^`2Bq@e`Tu*PL@ z0<)1zaBSogJdAus$chOu>q@vVl@l`Vtdx)#EoMAfZ^E1PC46k|%J{Q#Le2&ffow1l zWIT5!lnp1s*}6m>n@gGcY$OrMHY6IdjfqC!amglK)SETWtDqXpqPh!aUN#G9zITO0 zix$%SFt)-d!`P+;-bIOay+aGm^dUqhIHYsa&dr>g!U){gYNlmUZ@&3w{IUC>Dk+ukYN zQd36me0mB5WK*{ac{O89O{H^FrA0acQQmf^b7@P}CT%%I^rWS$R&p|DgkGDf*rU~!Y3K^Z)LDNbSORX{jre)-7<~%)&)AA{L4X5!yT!Uw4 z1G>}jvF;(O{NWI?%Em&-`Iz(QGMW~h&DBxEjs!-Q+u=K=n8y|bL#bWH(=0@sd1S4=kD=85=GE)4;}dGDYM+m=vLz|c`&aq*LmWSo+?jlec(tSY3LO8BV%ln*BD z!0Dj^I&^zE(BOvf0`;5v4Iu)ful{ELrVv>bBL8q9$+sN{-=4WKvl-}I3v{jrx;CY* zRjI4uPJNGrSW!k|!_%UKJl)UCE_l<`W5+T6Egt%&@Vfz^9`xd&*M$cMnkfA`hW<-F zM#JSAJUicmcz7Os9J|dUiw7Cjz+$`Pnrhfrp~s?8$eOb{k3GopRk&pWzy&jK5gc%_ zDgXp;3pn!C(K#DKb3X3#ii7sLql z2iB&kS)Xgw_kg|~&n?3ABi_lmyWI7FBk$axB2xj|Sq%RFV|b!H$Wk16$fJ=xbr-6- zpF_7^vbt+_waxQz$|YYyJ= zK2I(AGNOsX*~6k&nrmly{(K?F@_=F)3Mu4Ro(CKTu&=M=fxMB)Kt71a3d{`higFeNx!VF z9VruPt;TlvbXn0;j-IyX#HEy;r`gaJnX(KpVgjM=%aFzPR4WOrn>6ecXeFo-XwD-2 zz&iquNmB&Fm?z$vY*crrceAd0t*(1R=-IAhuc8nY+dhY!mD!Y9R;3oeonZ8X#?5GK zEgD-7^e^(;a>u%?EOM~Yu>a>1>yg-^XIpC8kfKEw@&s@DZunLsu??wzI}q9obgTtB zw*A4aXy<11@LKdRWVm4G4&sB}eCDpbYD3?z4lnvQq+?r>{I8-2>(40i zwS94GhMoPf)cSApDtwQtgClYLYk4?~evgM`;Q<;t0`$WpcsM9LJStH76&Xa9-FPG- zEK4G#Weoh~AnU^|BVm4dfE#H<%ZDUNA88u#^DBN4=#?-J{FMlXT`P@&kpX^XA09a% zt?YMEdVmLhiq;oSqo$(>x?@52U&=e~GPiqqcNx*xtj2W}X{Rel>%5Tum#9k4@=$`c zo=oPnjIKbOKtY|Pj;EOEsa!H+#^*wnh$^uZLe(FSi8Zl7A<*W{S<@EuOKA(rXcrYO zWNq<0ffB5g4e2#2PAXqu?^H{Nk{4j@ZFtN9=yt28>bjSXF7>U31~!C)+k*T0$tx!p z&;0Q84v4c#kNUi-(qfK4bx(5Rv3<5%RW&08^`ARw&gN2Sqoh_cLk`ki?qu4S0`&-0 zj8H?^UJ5m(Dv;rUT}K(^e+uP)5QJhxsluccVqBYyPbN*BRhF!xWOaeOc}thgm4XRu)2bk6hT!@=5mI`%wei(31Jut(LBTAn|(G`mDsL{Q*WFaKWn>T zJbU7;F`EbUBoxVQ@5HQW>Dd!tnO`9CBHc_&l4sJZS%dyNd5sLil-4TdZ=fsk7-Jh9 z{0s#?LGmZa`&ZQS7u5ABItITr+8_NCy}5?ogn;*l7WjpUYr(B>!veSP?RC_!;@9f)$+a8Z&0f&kKB={HSKIWm`4KIvdAGe3^TW=j976d!%8*1PNdve)bEHlcFkx>-s#C3RXbX`zWj5+^R9E;;BTWNCJ-jYe`t zT7nllY@m=sF9`&kW3R3ApY&4WEp~-XDJ_KF4E8Cf&WxnhCN`$T1DbjB=Dnwx_j~${ ze$8gnfVPism>UuRf3r#0iQ#zg6A{*d0Tf_x25)hQS9l~S0!Qb9C8C6qV6tdQD5)fw zoUn#aN=Y$UveGD{WYDlO%;rfei*ia1<&``tC4)6e$;MfKi z>_RCUDL8JVA>R;<%nzb+hR8yLH-?E^S;^LNosX_Lo~+r1JZrkknx`*8ESt9JnVMyG zG|zPG`oA<-jrRp&>ZfD78t0d0VMA+M9$C4Eon?qU6S_p7x~E|m&N~Jqlk7Z14qjRC z9IQ1V2~?TYJZ({P;R1AB@`icSFf8~;!_Y6@b(&4nZpNxw!k2UhA;4Ix}VZD%Uaa*2d*zcj2%q3lWsy!wMb-${e@ptpl&WwhBC|XU&Tc1}$p;PJ6{gxqroP@WJ95=M6<>txP1vqaj2-99ZQRKuzqp zX_>U^?2rr{-LV^HvyGv=NboXk*VAkr*3-=H8{Bkfm_)tU`DSE_D-#2o@7Qq%%;xjeB45%S3@;I(zP#e6gNQ1b;wrJplgFJVT^AgdKqj}78{I8T?vBgrkDot2 z6!>ELFpsT!DT=xgmJkKD6_7?`!p8TA@_+Y|jb3!By__6{g7i-F zXw|UR8i}NMd@CQvd6y#F_wp{E%KOZzylK(0cJj`>vwgb{BPkvYelSCX3WUx>_HiCd z1x8HSk4$e##!lNKgx-#7usK2$F6<)}6}(Mtu%4PxrnIMhi!;gF#UG?oN4P;+kk3t6r7_qBHPWR?+YV_sJUTU&?ZC?V3 z^r=pKn#K^u#ZAL}^zU@&>uROI~zPMR_E99}t7v^?(YO_pf@EFsH*Fh32m<)l0V~jKN~GVyN%p{ z?yHfm;i7t2GtS|(FqD4=?9{9h-V9wO_gdS6U*pe+BPC|{HtF^Sj^q9S z7hZ$&d*I7G+E2d*^M8W-zk~aGp!Qd4^x3Vg)VZ#-FBQ4`GkqVB;iY~+hy4o`F86Zg J5Rier>OXZ}GnfDX literal 0 HcmV?d00001 diff --git a/bot/core/__pycache__/middlewares.cpython-312.pyc b/bot/core/__pycache__/middlewares.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..280ce1f8cb7badae6b177c95a7fcf1518ec702a2 GIT binary patch literal 3129 zcmd5;U1%KF6~1?N{`OC@w3g%*sybF2taYMwEX(~-6DO)wVkeH&L@h0A%&^+I+N?7_ z&YjsfyOkg$rr6LDxzK9C6#Q1XqU};zaNh!XYhM)G!S+zogr+2U+hUctekeI-W>#y- z4uL+DUYIlIo_prpbI(2JJM))xIzeFkXU}&kLnfOlk=Q z!HN}PmRJxisUT65$4uE$3QE9>rfS6t@qm}igq18L170>$R=SW5c*X3px(nTu2!wUB z9cwh)t~PnMadyWtd;6F4=Ua+&c`=x|6OqQSWHU3je!MhX<7C>XR5GXy3w ziOEc1>VlAk^|HX?Ohqo78!;vs;{6(i1iGprpA`#~s-M0q#ehbxu(~*x@zL z(N1&cwTi(sBlssJKV9=xT`xfm=z4u*I=cM_ z(k0*4LCfwGkWa|nH^{~a8O~ii`56)7`4*Dpy*Gy+JvY6aJwJOZt6l0_6|ZH-Ze+%; zrp8(ltl#}0Gj{i%5*dE%-|i?_c{4dde=3d(7ieDoS!`VRdG7@M6@5Zpl_%(L>A29O z6ZH4O1f98@L_h7K#dO_I=(^n$e1)>xNU(b&j~evAj5Dr5|%W&M_8T zMlt~8GPwhk@O~s+ZGwzD2jncdB|g;>GgAJ8o^0dr>O?cvoNKC=53dhSUODzo=}$B3 zgU`L!^L$GJm6l9)47U{IRMMSUKG=vYf8)H}ilZb!66uX3aQv(7UH+#a&~qGsr(%~o z1z#WS@BttqG=YXzu}hAHO!YLRCv)@LbE+3ku%*s1#6g|^0jfK!^PmS1i!O(Uy5rHQc+@`*y6pk>HX}(z5K7d$DnQ-k@xW>^-H`@ zMBb}g{eB2`Dgn+$*csra7~o~H{^w0(flPTY2Rb12{|}8Edqqz0l^3A*7R$^}V|$-3 zmR@1T3wjbW#fqtK|T+b8+5>2DU+Y$Ebof^oqeB!!1;7B06B38;5Ct^GHHWLy)TvK2ZFdP`(e= z-9G{ep!~BvB>v5hl6}jp@q_EhM{hoU;CHjXo?T`u&IRX2|LE2J(RZ@vp1qmbwK92O z@@nSL`tC#LrvIAief#+NX{Gwh8o|$G<~fvccVMEuIARe zbN5`Vnm3PhAK69U?V(5d#dmup;Ai+Qkn>?A0o(@gz8j}V_QJCX@8d0TSlahx@D3^w zyd$?2-cb_5J8G9O03pV?n?2``uT~qFH*G zS+zW5Nxq1GmKBHN4f{#_bv5Sm_)o`^DCtE>gx`9}u@@?3j&R8FN0C2{Bxr6y2)2gh zp890iMi28tphw|xp9a#3QA%%-!H>y-YvjOfGIE=Y-X{D1K_0nHav#Ps%SW%pzw(B> aA@|e#rLGMEuZ{8DbYG+EUj$x396kr3s`=9Z literal 0 HcmV?d00001 diff --git a/bot/core/__pycache__/scheduler.cpython-312.pyc b/bot/core/__pycache__/scheduler.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4c216418172eae45c2fc33f7272f5a7bc5116d6b GIT binary patch literal 6054 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 literal 0 HcmV?d00001 diff --git a/bot/core/scheduler.py b/bot/core/scheduler.py index 4a298ef..583221b 100644 --- a/bot/core/scheduler.py +++ b/bot/core/scheduler.py @@ -49,12 +49,19 @@ async def check_and_send_reminders(bot: Bot) -> None: Args: bot: Bot instance """ + from bot.db.base import async_session_maker + from bot.db.operations import update_reminder + + if not async_session_maker: + logger.error("Session maker not initialized") + return + try: time_service = get_time_service() current_time = time_service.get_now() - # Get due reminders from database - async for session in get_session(): + # Get due reminders from database using proper async session + async with async_session_maker() as session: due_reminders = await get_due_reminders(session, current_time) if not due_reminders: @@ -74,16 +81,15 @@ async def check_and_send_reminders(bot: Bot) -> None: # Update next_run_at to prevent sending again # (it will be properly updated when user clicks "Done" or by periodic update) - from bot.db.operations import update_reminder - from datetime import timedelta - - # Temporarily set next_run_at to current + interval to avoid duplicate sends temp_next_run = time_service.calculate_next_occurrence( current_run=reminder.next_run_at, days_interval=reminder.days_interval, ) await update_reminder(session, reminder.id, next_run_at=temp_next_run) + # Commit all updates + await session.commit() + # Small delay to avoid rate limits await asyncio.sleep(0.5) diff --git a/bot/db/operations.py b/bot/db/operations.py index 3dca3c5..486a871 100644 --- a/bot/db/operations.py +++ b/bot/db/operations.py @@ -176,8 +176,11 @@ async def get_due_reminders(session: AsyncSession, current_time: datetime) -> Li Returns: List of due Reminder instances """ + from sqlalchemy.orm import selectinload + result = await session.execute( select(Reminder) + .options(selectinload(Reminder.user)) # Eager load user relationship .where(Reminder.is_active == True) .where(Reminder.next_run_at <= current_time) .order_by(Reminder.next_run_at) diff --git a/bot/handlers/__pycache__/__init__.cpython-312.pyc b/bot/handlers/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..df769eef266d2091f822292aa024c60d93692a52 GIT binary patch literal 154 zcmX@j%ge<81SZO^nUX;IF^B^Lj8MjB4j^MXLkdF_LnWgoQFrQ_>~NwK^lKaB;}Xr!&Ku*uC&Da}c> aD`EpG1X)uIvf=|XBO~K228kjTAO`^Y`Xq}0 literal 0 HcmV?d00001 diff --git a/bot/handlers/__pycache__/callbacks.cpython-312.pyc b/bot/handlers/__pycache__/callbacks.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ce2b30027374961cb515d3c0d0aa9bc4c7966d2e GIT binary patch literal 11491 zcmeHNYj6`+mhLOHWJ$K=hiu8%fSd5L0Lw5u5*%K_CNUVy!z=+Mvnt_kz(xQj%wm3=HBDRD*Vkelk$JvA<;z&3nPMT)pWeHcrMP*0ao$y3FiSkH!q9Rg} zsEkx5yb&*b=Zse+sw34@E{oSBY9qB&cEx>(x=07p;1bbC6ls98 zjrUwG&*w~ooZ3sqfFq5Ns>`REglPjS%}EtvDB~GuFQiRLun(*<E;Nq+Kntd+5_D5{K=jKP!vv10tu~#QwXX%xjwAb=d^EF3XG^cXQoa!yD z&ziLLZ?c;HDd$vJ&48un#~w+~4PUe8X_lU6Ka!psr|en(j!l+c=S=7^E~KztJy*!h90&RQl`Yuu+EF0DLCm#VEJZCi^0K~Aa}T z8L)iC=4hz7(FNq?oGu+UZb!2 z^zt!mI{ykr;m3N3Sbs8_5Rw_|n`(1BQm-KXpuZ2tT#cpE{Rtr|ssXe_Ro<}zPsm8KNsW9gVyCg}^HIYl9z5tBWAcJuQ=?1bkeJom-`V7nOt zV4u#v982$q4y@OVf`q17*cE7>2j; z_RH*KH3>6F(k`>sK)ERu;v@EfibBeiOfWmjLa$ykw-6816l7E49Y@$-GQ9IGyIH$< z9)y`>4rPHUbzX+d3c_M zr}H=V7f8@^_&pB?Km81H^E+Y3%r{S8E0>6g2RYF=99&G|`cjEQc;xtyht>;=`=xd& zVJqhTYUetP&B#5EXYYXmbOW|?+hU?5@cC*SZp(aGV|TW5oshdXCJCI8Lre60wE(6s zzaE7qxnO*0|d|`rP3Ly8N&{u<@JOFS@E^?mW6YP+8UK8> zeyLKwbm-~f@2jhKDXVv7>z`4po;lX_dAV=Q>pzuxIVI2BBtP@)Pg7a%bE@k(+4bC* z%lms@v+8S8d~HK6b#bS%xHIe9aBTBuo?6w@sCXJx&m6@wCubw&>&V!;&BK5ByX`qU zac?8{?Dlf!9~ryDnWKS=DfgXfd$~<+Y|DBUtL$Q#UHp62^HTTm?$g1uUFW)g(S3Hc z+_LVY1~uHPgnQNSE+xE6UiXY#z58Q!Pi_WNy_?+6IT`o&A@V@G_j4}Bv1I(-Q!vXD zb2=7~Uy+W-*k4ZvX~a%C=CC7d*a?YI59yf4j+Qr|Jezd1u%mO3Vk&(D24JoN#pmUKfrsuC5nER42Ar%&4S-{EAmssGz|$$ zZByw4ge@vRXa~fa0Z$o4E%xxM6a-Av(ywU?Zs9>kT6g=H>#2XK z4_!E_wsk3OUD^7LIR{fd_a0Mv!)HBBD%+&6O*yx@X{V1%IIK&!#FqPhc5KVsr0aGf(RPQLET~NKF9*q zLK~)3N=x}A^On76H8rlfL1uZ*E#B1+xrD6B* z)I>V$IZ#jqyy8qKAuhpygFtf}NM%Hc0)_Y(=FY}o4h984nU6`JE*LS00jg5sLI?_X zvyLdfiHJfGRYclk2NnjdXTojVs?@iRxvEajP-_+_H483mQ5UUM7OlN!xB21Xv{gHg zb^XD`RMb6+%eir^ao*XP=by*BdBNmYb8FTUQrVEqhK#Fu%;P)Vb*B5Z?$fK!S6)b{ zp|BDP%dP8k4Cx@gF<+DFo2&Tds=gM**CN*jvHgW#+40t&1v7w)y6C=c8<(Dj#W>N{ zX(LxiM>~6UI!FM09jgHP!cItx){~Ak?5Mv1}ZOBbnlo4Kt0j=Wqs1F)t16t$eI zkhl)d6>2G6HI<)h^50|Ss~jjuufj_(qR_TF259$za*6{Z>>5p6=SDB(&i(vn9Bmbb zRzho1PL19SWf0ipa}OV(4y4sOal{w!(?ju7^U`A%H7%BcvNbhm2HAotMvWeE5sXJd z76dO59YiY(5T#v+cv}o&p${Rj+A_R~)$^v+mI^b35FG?Zax7Hdf4Zzd85W_IeH{f}Iy;-5uuNZpa zqe^w%9%bF0Y<)zniaZSQ9zA=rJnLDZvMXeEMF~(`IozVQZ&unjtL1!u>Y93y(~D3FhUp-PG_VaOaM1 z$h{PmA9R4WQ{Y~lhfhy9uAOwEmg5?e4pKA4>h}0<^_>h_Kk_@E1W*!}qeSZvWp$^Z zT*UQI3w=gHGTomZ1fG+|z?X_k;mt$_26at~Qm`D76R4MZW6SHGJ!;HddB+6Xga1Vd)EYah`#JodrWJ{_zCedEzS2oS|g#Zy?VI7T)kSi>_b9 z=0PhZd_GgLe-H8Y;CaYf1BEe|rvYq-2_wieKqW@Ov%KT7bF!MiTG+qA8d#Z_2_u-) z-f>O7YUw<)RMJo7F1-c@LsQD$$#X%46$6IG>N7&t^%HpR!1E?N$Ki>>(`7I<`o+EB zMWGM8u6g4|_sRlG!^QT2GZuVC)L%;dpWiJIpw2xtaiiIisSI9l^51|n1~CFJV(K$O zng$#{kfe8WsK?6jAUTpdcjmRpZumUp=yfyrttNDF+q{rF`z6CC2)|+dB7mi%8U++jFKY267+8-V7sIDH_)no8FS#PuIYL;Ei=xnK* ztJXcK)IDkNLM=*73-Cep$Olz9k3Efi&{WQvA_GUByCduARoPyd?H%*f>h6~XSWAex5$g1lA=2q#uLM9EagojncEsI+@)FYNWk8xf)t7fD8Jl31Kx2YiU@AVFs1DyMOfyQ<+4= z8!Y16;K;lo57Qme2VW-tL*%78#V!!?I)$}_Q55_(1|JUpuw>*-<)NV-7l+|(dCq#{ zOF}x`pWH8*UgDNR@mQa5AQgxIp9q#b--ai#o!bez!hSK9;EWvFY-S4#chV_?hWxj1 zxNgZel%K#ky$uqaT1p7y*X9~}XbbLDIM_%$8pMA#}B*6t*Srpv2ebJ~^7VA&pcNcLB zipY*=l}1)5J$OivMBK+Bs3!Dz1_LcN-CxMVpE38UIgXY0mViiwNTydZ`PAtS)pBiASv# z-=k+7PKB=d?H7@G)LhXh{vS>>N|72U4*JhYI$@7@kmfaA-ckB*5}I>ge;jU1aU;B> zPH*bGql7!eO@!y#l|H>@>lxh1T>m;_X7!14&dGb>R{#Ja-1V48JTb^~#IOhD^U3L1| ze|FD0=KQ2?PPT5I%+!2R)ts%Gb*v&+!Ps0X@hikH2bRf!RyD9p2`n4hetq|q-5>dt z7xV*8(dCH=Qd9{#DKEAD;wCDC7W`#X=I1K3MkM)qF^*n zMZJ9#v4d_HG0lF$GUNx=*}4c#q}N>MUUQv$%^vWjF#{CMHKEyGf1PWMb%vNu0b*mF zK{DIK%mtP~x1Ro?8faAltruc{ci`fI;T9#dJ{#!BlFpp1*;sLiKl447b3kk?2}=5k zfP_tNfCa(KO}OMQ%{)HyG&$pZ%_%o7SE`q1$qM|y&hwAw7>F*UzrYBqJ^lyG7ylei G!T$i%;P&nS literal 0 HcmV?d00001 diff --git a/bot/handlers/__pycache__/common.cpython-312.pyc b/bot/handlers/__pycache__/common.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9c916a088fc30ecd1a93ba9d343f2de22ba66b7c GIT binary patch literal 5085 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 D(Mw{+ literal 0 HcmV?d00001 diff --git a/bot/handlers/__pycache__/errors.cpython-312.pyc b/bot/handlers/__pycache__/errors.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..558a073ca653529534e8c0f04f9acff8564285cd GIT binary patch literal 2346 zcmbtWUrZE77@yg_U2cy%Jda?3L)nU2F?f^~sv-412P7pXB|g-9xh%KC$+>q&XYYzf z(SS5nTNCu9Kup7H8*QSkMATMMFn#FDu5EI3Qy)xY(!QNS(rWwAZ#<3i9LZ3^}s6cGBEDTM~Q-4@TmFpg9dLMm1{4ad0yFLN3rbRlHQPf|QcdSk@_f<`8_3BvPRH z4iSw+sS@9>sNLk_#hlLppk6>KSDfJj`qWX}a*4kP z(XoaRc-T9>tQUG3ERM(A1&`H{HcBsGDdrtpvpTaNsgA<_k0MogAF}ibKhA$B2oPUJ zC>{yzERM%~1=iJ(HoY*yBHl$KEK!}8q(at;MVS#Y!VYvcREJXD!pfTv-FO`T!~Tmy z7ax6mnQ+>&V9&p+7_R*-`YD+%7a|1 z3^&XPeBr)CZ!$drSv021VdIuDV_Y+CnWv4L#%0+SW{fMw4dZe^Hm1OQ+jhEQjvCix zW7<4po|gf+Y+RFJ=1pS;26M!?4W2j6v&J>suQ8$|B1Dsos{oEM)|1B9#hyDkx8z- z>AnB|D*}gDJ<^XP2f_*zwAA1$Mc0nNzVs-OqpOS8yDTwZ!UQ`$OIq12OA3c0nxgCB zu;mPgSzQB3O!uowidZH253xigp$|X_l!AqAw#o_%g`rl`Og%>>_(ls8oz)asezvYB znQF{eU%k;@SP%4PERQXQ^A=hS-evI9cR>C81^qsZmb^$PJ=HbRwcx6rXqnnGxhLyy zHvP?6|1Q(N%c$Nx(=%J~ZS9>}WAEFBvwLCfy7AicwK)L^YnKo&h&eZMdQJ_U9GVcO z+>`EXWyAf-h8!nI9eBa_(s;x9hOBRk>D!X^Z8v?}a~xWGlw0Jv^0MC$=P7&4I-qc^ z8LRoIW@7VH!(>CYy5)X#OO6wz&Q%IFIqPdSea#Er?gc*!puA-f@r;LOJkSB=f8%sb z&I6oJmqg^PdV(;-@sry()^(=K@b8;_dA8iB3TEByrn~)*9M7!JaxR$rbjg|b?_BlY zKif20XH>Ok-5sX8!}jmQf9fY7fhYI97Occ~TDBf&MR(WZ13MjeH#nHQu@3M#aa-Fq zH1{fQ+v=EWaxl4tXZTJGK69;7+h%^AuWXa~dA|Voyeu$eGxM3>iot(=n-r|z=U=Z3 zdii^$%;%n00OVc;^QkYhO2T0^8G++dqVy%%OG?>0XL<5kAeHGSI%RL1@rarO9MILe9$F_-X1meE{weD&V literal 0 HcmV?d00001 diff --git a/bot/handlers/__pycache__/reminders_create.cpython-312.pyc b/bot/handlers/__pycache__/reminders_create.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..267a88103e717a263e5db4a012272e225f010ca1 GIT binary patch literal 11093 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 Wtc$54_0vr%>*(iBQk8j3k^cdr(fl<4 literal 0 HcmV?d00001 diff --git a/bot/handlers/__pycache__/reminders_manage.cpython-312.pyc b/bot/handlers/__pycache__/reminders_manage.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fc73270e64102f4065705cc1fd335a580747b5c1 GIT binary patch literal 20972 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 literal 0 HcmV?d00001 diff --git a/bot/main.py b/bot/main.py index 5e52129..a37e23f 100644 --- a/bot/main.py +++ b/bot/main.py @@ -38,14 +38,23 @@ async def on_shutdown() -> None: logger.info("Shutting down reminder bot...") # Stop scheduler - stop_scheduler() + try: + stop_scheduler() + except Exception as e: + logger.error(f"Error stopping scheduler: {e}") # Close database - await close_db() + try: + await close_db() + except Exception as e: + logger.error(f"Error closing database: {e}") # Close bot session - if bot: - await bot.session.close() + if bot and hasattr(bot, 'session'): + try: + await bot.session.close() + except Exception as e: + logger.error(f"Error closing bot session: {e}") logger.info("Bot shutdown completed") diff --git a/bot/utils/validators.py b/bot/utils/validators.py index 281c145..0482f29 100644 --- a/bot/utils/validators.py +++ b/bot/utils/validators.py @@ -45,11 +45,11 @@ def validate_days_interval(days_str: str) -> Optional[int]: days_str: Days interval string to validate Returns: - Integer days if valid (>0), None otherwise + Integer days if valid (>0 and <=365), None otherwise """ try: days = int(days_str.strip()) - if days > 0: + if 0 < days <= 365: # Max 1 year return days except (ValueError, AttributeError): pass