modern
This commit is contained in:
parent
9295538f5f
commit
a7c047f847
3 changed files with 94 additions and 23 deletions
|
|
@ -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 <id> <текст>` — вписать текст в макет. Доступные: `1 — Владимир Владимирович Путин самый лучший президент` (737x414, точка 104,240).
|
||||
- `/gen_mem Up:верх Down:низ` — прислать с фото (подпись) или ответом на фото. Можно указывать только Up или только Down.
|
||||
- `/break` — показывает, сколько минут до ближайшего перекура/идёт ли перекур.
|
||||
- `/schedule` — показывает расписание на сегодня, текущую и следующую пару.
|
||||
- `/schedule [пн|mon]` — показывает расписание на ближайший указанный день недели; без аргумента показывает сегодня, текущую и следующую пару.
|
||||
- `/talk <сообщение>` — побазарить с ИИ (контекст 100 сообщений).
|
||||
- `/penis` — миниигра, 1 раз в 24 часа.
|
||||
- `/top_penis` — топ по длине.
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
111
main.py
111
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))
|
||||
|
|
|
|||
Loading…
Reference in a new issue