Files
VLNKI_Bot/scheduler.py

144 lines
4.6 KiB
Python

# scheduler.py
import datetime
import pytz
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, # Friday
"create_hour": 10,
"create_minute": 0,
"event_day": 4,
"event_hour": 19,
"event_minute": 30,
"key": "echottvt",
},
# 2) AS VDV PSG — создавать в пятницу 22:00, начало в субботу 16:30
# ВАЖНО: create_day = Friday (4), event_day = Saturday (5)
{
"name": "AS VDV PSG",
"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",
},
# 3) ECHO TvT — создавать в субботу 08:00, начало в субботу 19:30
{
"name": "ECHO TvT",
"day": 5, # Saturday
"create_hour": 10,
"create_minute": 0,
# событие в субботу 19:30
"event_day": 5, # Saturday
"event_hour": 19,
"event_minute": 30,
"key": "echotvt_saturday",
},
# 4) TEST — создавать в понедельник 13:10, начало в вторник 19:30
{
"name": "Пробное",
"day": 0, # Saturday
"create_hour": 13,
"create_minute": 19,
# событие в субботу 19:30
"event_day": 0, # Saturday
"event_hour": 13,
"event_minute": 20,
"key": "TEST",
}
]
def get_next_datetime(now, target_day, hour, minute):
days_ahead = (target_day - now.weekday()) % 7
target_date = (now + datetime.timedelta(days=days_ahead)).date()
naive = datetime.datetime(
target_date.year,
target_date.month,
target_date.day,
hour,
minute
)
return MOSCOW_TZ.localize(naive)
# Этот объект будет заполнен из 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 # ⛔ автосоздание запрещено командой/состоянием
now = datetime.datetime.now(MOSCOW_TZ)
create_poll = event_loop_context["create_poll"]
event_tasks = event_loop_context["event_tasks"]
generate_event_id = event_loop_context["generate_event_id"]
for event in SCHEDULED_EVENTS:
# День и время создания
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"])
print(f"[{event['name']}]")
print("NOW:", now)
print("CREATE:", create_time)
print("START:", start_time)
print("CREATE_DAY:", create_day, "START_DAY:", start_day)
print("-" * 40)
# ✅ Догоняющее окно:
# если уже пора создать голосование (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
info = {
"name": event["name"],
"start_time": start_time,
}
print(f"🆕 Автосоздание: {info['name']} в {start_time}")
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
event_loop_context["generate_event_id"] = generate_event_id_func