11import logging
2- import time
3- from datetime import datetime , timedelta
2+ from datetime import datetime , timedelta , timezone
43
5- from aiogram .fsm .storage .redis import RedisStorage
6- from aiogram .utils .i18n import lazy_gettext as __
4+ from aiogram .utils .i18n import I18n
75from apscheduler .schedulers .asyncio import AsyncIOScheduler
6+ from redis .asyncio .client import Redis
87from sqlalchemy .ext .asyncio import AsyncSession , async_sessionmaker
98
109from app .bot .services import NotificationService , VPNService
1514
1615async def notify_users_with_expiring_subscription (
1716 session_factory : async_sessionmaker ,
18- storage : RedisStorage ,
17+ redis : Redis ,
18+ i18n : I18n ,
1919 vpn_service : VPNService ,
2020 notification_service : NotificationService ,
2121) -> None :
@@ -31,7 +31,7 @@ async def notify_users_with_expiring_subscription(
3131 user_notified_key = f"user:notified:{ user .tg_id } "
3232
3333 # Check if user was recently notified
34- if await storage . redis .get (user_notified_key ):
34+ if await redis .get (user_notified_key ):
3535 continue
3636
3737 client_data = await vpn_service .get_client_data (user )
@@ -40,25 +40,31 @@ async def notify_users_with_expiring_subscription(
4040 if not client_data or client_data ._expiry_time == - 1 :
4141 continue
4242
43- current_time_ms = time .time () * 1000
44- time_left_ms = client_data ._expiry_time - current_time_ms
45- threshold_ms = timedelta (hours = 24 ).total_seconds () * 1000
43+ now = datetime .now (timezone .utc )
44+ expiry_datetime = datetime .fromtimestamp (
45+ client_data ._expiry_time / 1000 , timezone .utc
46+ )
47+ time_left = expiry_datetime - now
4648
4749 # Skip if not within the notification threshold
48- if not (0 < time_left_ms <= threshold_ms ):
50+ if not (timedelta ( 0 ) < time_left <= timedelta ( hours = 24 ) ):
4951 continue
5052
51- # Send notification and set Redis flag
53+ # BUG: The button and expiry_time will not be translated
54+ # (the translation logic needs to be changed outside the current context)
5255 await notification_service .notify_by_id (
5356 chat_id = user .tg_id ,
54- text = __ ("task:message:subscription_expiry" ).format (
57+ text = i18n .gettext (
58+ "task:message:subscription_expiry" ,
59+ locale = user .language_code ,
60+ ).format (
5561 devices = client_data .max_devices ,
5662 expiry_time = client_data .expiry_time ,
5763 ),
5864 # reply_markup=keyboard_extend
5965 )
6066
61- await storage . redis .set (user_notified_key , "true" , ex = timedelta (hours = 24 ))
67+ await redis .set (user_notified_key , "true" , ex = timedelta (hours = 24 ))
6268 logger .info (
6369 f"[Background task] Sent expiry notification to user { user .tg_id } ."
6470 )
@@ -67,7 +73,8 @@ async def notify_users_with_expiring_subscription(
6773
6874def start_scheduler (
6975 session_factory : async_sessionmaker ,
70- storage : RedisStorage ,
76+ redis : Redis ,
77+ i18n : I18n ,
7178 vpn_service : VPNService ,
7279 notification_service : NotificationService ,
7380) -> None :
@@ -76,7 +83,7 @@ def start_scheduler(
7683 notify_users_with_expiring_subscription ,
7784 "interval" ,
7885 minutes = 15 ,
79- args = [session_factory , storage , vpn_service , notification_service ],
80- next_run_time = datetime .now (),
86+ args = [session_factory , redis , i18n , vpn_service , notification_service ],
87+ next_run_time = datetime .now (tz = timezone . utc ),
8188 )
8289 scheduler .start ()
0 commit comments