From 53c1d39d04ea934138c87377239130c7ce28882a Mon Sep 17 00:00:00 2001 From: Pustoy Date: Mon, 16 Feb 2026 12:47:57 +0500 Subject: [PATCH] =?UTF-8?q?#=20=D0=98=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD?= =?UTF-8?q?=D0=BE=20=D1=80=D0=B0=D1=81=D0=BF=D0=B8=D1=81=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20#=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD?= =?UTF-8?q?=D0=B0=20=D0=BB=D0=BE=D0=B3=D0=B8=D0=BA=D0=B0=20=D1=81=D0=BE?= =?UTF-8?q?=D0=B7=D0=B4=D0=B0=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scheduler.py | 73 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 57 insertions(+), 16 deletions(-) diff --git a/scheduler.py b/scheduler.py index 370cd5c..d197f44 100644 --- a/scheduler.py +++ b/scheduler.py @@ -6,49 +6,79 @@ from disnake.ext import tasks MOSCOW_TZ = pytz.timezone("Europe/Moscow") +# 0 = Monday ... 6 = Sunday (datetime.weekday) SCHEDULED_EVENTS = [ + # 1) ECHO TTvT — создавать в пятницу 07:00, начало в пятницу 19:30 { "name": "ECHO TTvT", - "day": 4, - "create_hour": 8, + "day": 4, # Friday + "create_hour": 7, "create_minute": 0, "event_hour": 19, "event_minute": 30, - "key": "echottvt" + "key": "echottvt", }, + + # 2) AS VDV PSG — создавать в пятницу 22:00, начало в субботу 16:30 + # ВАЖНО: create_day = Friday (4), event_day = Saturday (5) { "name": "AS VDV PSG", - "day": 4, + "day": 4, # Friday for create "create_hour": 22, "create_minute": 0, + + # событие в субботу 16:30 + "event_day": 5, # Saturday "event_hour": 16, "event_minute": 30, - "key": "asvdvpsg" + + "key": "asvdvpsg", }, + + # 3) ECHO TvT — создавать в субботу 08:00, начало в субботу 19:30 { "name": "ECHO TvT", - "day": 5, - "create_hour": 8, + "day": 4, # Friday for create + "create_hour": 22, "create_minute": 0, + + # событие в субботу 19:30 + "event_day": 5, # Saturday "event_hour": 19, "event_minute": 30, - "key": "echotvt_saturday" + "key": "echotvt_saturday", } ] -def get_next_datetime(now, target_day, hour, minute): + +def get_next_datetime(now: datetime.datetime, target_day: int, hour: int, minute: int) -> datetime.datetime: + """ + Возвращает ближайшую дату/время (timezone-aware, MSK) для target_day/hour/minute, + начиная от 'now'. + """ days_ahead = (target_day - now.weekday()) % 7 - next_date = now + datetime.timedelta(days=days_ahead) - return MOSCOW_TZ.localize(datetime.datetime.combine(next_date.date(), datetime.time(hour, minute))) + target_date = (now + datetime.timedelta(days=days_ahead)).date() + return datetime.datetime( + target_date.year, + target_date.month, + target_date.day, + hour, + minute, + tzinfo=MOSCOW_TZ + ) + # Этот объект будет заполнен из main.py event_loop_context = {} + +# Включается из main.py (командой или on_ready) AUTO_EVENTS_ENABLED = False + @tasks.loop(minutes=1) async def scheduled_event_loop(): if not AUTO_EVENTS_ENABLED: - return # ⛔ автосоздание запрещено командой + return # ⛔ автосоздание запрещено командой/состоянием now = datetime.datetime.now(MOSCOW_TZ) @@ -57,11 +87,23 @@ async def scheduled_event_loop(): generate_event_id = event_loop_context["generate_event_id"] for event in SCHEDULED_EVENTS: - create_time = get_next_datetime(now, event["day"], event["create_hour"], event["create_minute"]) - if abs((now - create_time).total_seconds()) < 60: - start_time = get_next_datetime(now, event["day"], event["event_hour"], event["event_minute"]) + # День и время создания + create_day = event["day"] + create_time = get_next_datetime(now, create_day, event["create_hour"], event["create_minute"]) + + # День и время старта (если не указан event_day — считаем что тот же день) + start_day = event.get("event_day", event["day"]) + start_time = get_next_datetime(now, start_day, event["event_hour"], event["event_minute"]) + + # ✅ Догоняющее окно: + # если уже пора создать голосование (create_time наступило), + # но событие ещё не началось + if create_time <= now < start_time: event_id = generate_event_id(event["name"], start_time) + + # 🔒 Защита от дублей: если есть в event_tasks — значит уже создано if event_id in event_tasks: + # Можно оставить принт — удобно для диагностики print(f"⏩ Уже существует: {event_id}") continue @@ -74,7 +116,6 @@ async def scheduled_event_loop(): await create_poll(info, message_id=event["key"]) - def init_scheduler(create_poll_func, event_tasks_dict, generate_event_id_func): event_loop_context["create_poll"] = create_poll_func event_loop_context["event_tasks"] = event_tasks_dict