From a7c047f8472229da990c972f1cf53956d892ad4b Mon Sep 17 00:00:00 2001 From: q Date: Wed, 18 Mar 2026 09:39:32 +0300 Subject: [PATCH] modern --- README.md | 4 +- config.py | 2 +- main.py | 111 ++++++++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 94 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 1b53fc8..7d0585c 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ - вписывает текст шрифтом Impact (белый с чёрной обводкой) в макеты (`/maket`); - делает мемы из присланных фото (`/gen_mem Up:... Down:...`); - подсказывает, сколько минут до перекура по заданному расписанию (`/break`); -- показывает расписание, текущую и следующую пару (`/schedule`); +- показывает расписание, текущую и следующую пару (`/schedule`, можно с днём недели); - умеет базарить (`/talk`) с контекстом 100 сообщений; - авто-ответы в чате (10% шанс + триггер-слова); - миниигра `/penis` + `/top_penis`; @@ -44,7 +44,7 @@ docker compose down - `/maket <текст>` — вписать текст в макет. Доступные: `1 — Владимир Владимирович Путин самый лучший президент` (737x414, точка 104,240). - `/gen_mem Up:верх Down:низ` — прислать с фото (подпись) или ответом на фото. Можно указывать только Up или только Down. - `/break` — показывает, сколько минут до ближайшего перекура/идёт ли перекур. -- `/schedule` — показывает расписание на сегодня, текущую и следующую пару. +- `/schedule [пн|mon]` — показывает расписание на ближайший указанный день недели; без аргумента показывает сегодня, текущую и следующую пару. - `/talk <сообщение>` — побазарить с ИИ (контекст 100 сообщений). - `/penis` — миниигра, 1 раз в 24 часа. - `/top_penis` — топ по длине. diff --git a/config.py b/config.py index e3ac69a..f5c14b5 100644 --- a/config.py +++ b/config.py @@ -187,7 +187,7 @@ def get_hint_text(templates_str: str) -> str: f"• /maket «id» «текст» — доступные: {templates_str}.\n" "• /gen_mem Up:верх Down:низ — отправь с фото.\n" "• /break — узнать время до перекура.\n" - "• /schedule — расписание, текущая и следующая пара.\n" + "• /schedule [пн|mon] — расписание; без аргумента еще текущая и следующая пара.\n" "• /penis — миниигра 1 раз в 24 часа.\n" "• /top_penis — топ по длине.\n" "• /talk [текст] — ИИ базарит на фене.\n" diff --git a/main.py b/main.py index 021b9ff..0d1bf6a 100644 --- a/main.py +++ b/main.py @@ -41,6 +41,47 @@ _weekday_names = { 6: "Воскресенье", } +_weekday_aliases = { + "mon": 0, + "monday": 0, + "пн": 0, + "пон": 0, + "понедельник": 0, + "tue": 1, + "tues": 1, + "tuesday": 1, + "вт": 1, + "втр": 1, + "вторник": 1, + "wed": 2, + "wednesday": 2, + "ср": 2, + "срд": 2, + "среда": 2, + "thu": 3, + "thur": 3, + "thurs": 3, + "thursday": 3, + "чт": 3, + "чет": 3, + "четверг": 3, + "fri": 4, + "friday": 4, + "пт": 4, + "пят": 4, + "пятница": 4, + "sat": 5, + "saturday": 5, + "сб": 5, + "суб": 5, + "суббота": 5, + "sun": 6, + "sunday": 6, + "вс": 6, + "вск": 6, + "воскресенье": 6, +} + @dataclass(frozen=True) class LessonSlot: @@ -107,6 +148,20 @@ def _current_week_key(now: datetime) -> str: return "upper" if is_upper else "lower" +def _resolve_schedule_date(now: datetime, requested_weekday: int | None = None) -> datetime: + if requested_weekday is None: + return now + delta_days = (requested_weekday - now.weekday()) % 7 + return now + timedelta(days=delta_days) + + +def _parse_weekday_arg(value: str) -> int | None: + normalized = re.sub(r"[^a-zа-яё]", "", value.lower()) + if not normalized: + return None + return _weekday_aliases.get(normalized) + + def _build_lesson_slot(raw_entry: dict) -> LessonSlot: pair_number = raw_entry.get("pair") start_t, end_t = config.PAIR_TIMES.get(pair_number, (None, None)) @@ -120,7 +175,7 @@ def _build_lesson_slot(raw_entry: dict) -> LessonSlot: ) -def get_today_lessons(now: datetime | None = None) -> tuple[str, list[LessonSlot]]: +def get_lessons_for_day(now: datetime | None = None) -> tuple[str, list[LessonSlot]]: now = _normalize_now(now) week_key = _current_week_key(now) raw_day = config.LESSON_SCHEDULE.get(week_key, {}).get(now.weekday(), []) @@ -169,20 +224,24 @@ def _format_lesson_line(lesson: LessonSlot) -> str: def next_lesson_text(now: datetime | None = None) -> str: now = _normalize_now(now) - _, lessons = get_today_lessons(now) + _, lessons = get_lessons_for_day(now) next_lesson = _find_next_lesson(now, lessons) if not next_lesson: return "Следующей пары сегодня нет." return f"Следующая пара: {_format_lesson_brief(next_lesson)}" -def build_schedule_text(now: datetime | None = None) -> str: +def build_schedule_text(now: datetime | None = None, requested_weekday: int | None = None) -> str: now = _normalize_now(now) - week_key, lessons = get_today_lessons(now) - current_lesson = _find_current_lesson(now, lessons) - next_lesson = _find_next_lesson(now, lessons) + target_now = _resolve_schedule_date(now, requested_weekday) + week_key, lessons = get_lessons_for_day(target_now) + show_live_status = target_now.date() == now.date() + current_lesson = _find_current_lesson(now, lessons) if show_live_status else None + next_lesson = _find_next_lesson(now, lessons) if show_live_status else None week_label = "Верхняя" if week_key == "upper" else "Нижняя" - day_label = _weekday_names.get(now.weekday(), "Сегодня") + day_label = _weekday_names.get(target_now.weekday(), "Сегодня") + if not show_live_status: + day_label = f"{day_label}, {target_now:%d.%m.%Y}" lines = [f"{week_label} неделя", day_label] if lessons: @@ -190,21 +249,22 @@ def build_schedule_text(now: datetime | None = None) -> str: lines.extend(_format_lesson_line(lesson) for lesson in lessons) else: lines.append("") - lines.append("На сегодня расписание пустое.") + lines.append("На этот день расписание пустое.") - lines.append("") - if current_lesson: - if current_lesson.is_free: - lines.append(f"Сейчас: {current_lesson.pair_number} пара свободна") + if show_live_status: + lines.append("") + if current_lesson: + if current_lesson.is_free: + lines.append(f"Сейчас: {current_lesson.pair_number} пара свободна") + else: + lines.append(f"Сейчас: {_format_lesson_brief(current_lesson)}") else: - lines.append(f"Сейчас: {_format_lesson_brief(current_lesson)}") - else: - lines.append("Сейчас: пары нет") + lines.append("Сейчас: пары нет") - if next_lesson: - lines.append(f"Следующая: {_format_lesson_brief(next_lesson)}") - else: - lines.append("Следующая: сегодня нет") + if next_lesson: + lines.append(f"Следующая: {_format_lesson_brief(next_lesson)}") + else: + lines.append("Следующая: сегодня нет") return "\n".join(lines) @@ -877,7 +937,18 @@ async def handle_start(message: Message): async def handle_schedule_cmd(message: Message): now = datetime.now(ZoneInfo(config.DEFAULT_TZ)) - await message.answer(build_schedule_text(now)) + raw_text = message.text or "" + parts = raw_text.split(maxsplit=1) + requested_weekday = None + if len(parts) > 1: + requested_weekday = _parse_weekday_arg(parts[1].split(maxsplit=1)[0]) + if requested_weekday is None: + await message.answer( + "Не понял день недели. Примеры: /schedule mon, /schedule fri, /schedule пн, /schedule чт." + ) + return + + await message.answer(build_schedule_text(now, requested_weekday)) async def handle_break_cmd(message: Message): now = datetime.now(ZoneInfo(config.DEFAULT_TZ))