Compare commits

...

1 commit

2 changed files with 119 additions and 52 deletions

43
Schedule.json Normal file
View file

@ -0,0 +1,43 @@
{
"0": [
[9, 50, 10, 35, 5],
[10, 40, 11, 25, 30],
[11, 55, 12, 40, 5],
[12, 45, 13, 30, 15],
[13, 45, 14, 30, 5],
[14, 35, 15, 20, 30],
[15, 50, 16, 35, 5],
[16, 40, 17, 25, null]
],
"1": [
[9, 50, 10, 35, 5],
[10, 40, 11, 25, 30],
[11, 55, 12, 40, 5],
[12, 45, 13, 30, 15],
[13, 45, 14, 30, 5],
[14, 35, 15, 20, null]
],
"2": [],
"3": [
[8, 0, 8, 45, 5],
[8, 50, 9, 35, 15],
[9, 50, 10, 35, 5],
[10, 40, 11, 25, 30],
[11, 55, 12, 40, 5],
[12, 45, 13, 30, 15],
[13, 45, 14, 30, 5],
[14, 35, 15, 20, 30],
[15, 50, 16, 35, 5],
[16, 40, 17, 25, null]
],
"4": [
[9, 50, 10, 35, 5],
[10, 40, 11, 25, 30],
[11, 55, 12, 40, 5],
[12, 45, 13, 30, 15],
[13, 45, 14, 30, 5],
[14, 35, 15, 20, null]
],
"5": [],
"6": []
}

128
main.py
View file

@ -1,11 +1,12 @@
import asyncio
import json
import logging
import os
import re
from io import BytesIO
from pathlib import Path
from textwrap import wrap
import random
from typing import Any
from aiogram import Bot, Dispatcher, F, types
from aiogram.enums import ParseMode
@ -40,54 +41,80 @@ def templates_list_text() -> str:
# ---- Schedule & breaks ----
def make_time(h: int, m: int) -> time:
return time(hour=h, minute=m)
def _ensure_int(value: Any, field_name: str, day: int, lesson_idx: int) -> int:
if isinstance(value, bool) or not isinstance(value, int):
raise ValueError(
f"Invalid {field_name} in day {day}, lesson #{lesson_idx + 1}: expected integer, got {value!r}"
)
return value
# Schedule format: list of (lesson_start, lesson_end, break_minutes_after)
SCHEDULE: dict[int, list[tuple[time, time, int | None]]] = {
0: [ # Monday
(make_time(9, 50), make_time(10, 35), 5),
(make_time(10, 40), make_time(11, 25), 30),
(make_time(11, 55), make_time(12, 40), 5),
(make_time(12, 45), make_time(13, 30), 15),
(make_time(13, 45), make_time(14, 30), 5),
(make_time(14, 35), make_time(15, 20), 30),
(make_time(15, 50), make_time(16, 35), 5),
(make_time(16, 40), make_time(17, 25), None),
],
1: [ # Tuesday
(make_time(9, 50), make_time(10, 35), 5),
(make_time(10, 40), make_time(11, 25), 30),
(make_time(11, 55), make_time(12, 40), 5),
(make_time(12, 45), make_time(13, 30), 15),
(make_time(13, 45), make_time(14, 30), 5),
(make_time(14, 35), make_time(15, 20), None),
],
2: [], # Wednesday — кайфуем дома
3: [ # Thursday
(make_time(8, 0), make_time(8, 45), 5),
(make_time(8, 50), make_time(9, 35), 15),
(make_time(9, 50), make_time(10, 35), 5),
(make_time(10, 40), make_time(11, 25), 30),
(make_time(11, 55), make_time(12, 40), 5),
(make_time(12, 45), make_time(13, 30), 15),
(make_time(13, 45), make_time(14, 30), 5),
(make_time(14, 35), make_time(15, 20), 30),
(make_time(15, 50), make_time(16, 35), 5),
(make_time(16, 40), make_time(17, 25), None),
],
4: [ # Friday
(make_time(9, 50), make_time(10, 35), 5),
(make_time(10, 40), make_time(11, 25), 30),
(make_time(11, 55), make_time(12, 40), 5),
(make_time(12, 45), make_time(13, 30), 15),
(make_time(13, 45), make_time(14, 30), 5),
(make_time(14, 35), make_time(15, 20), None),
],
5: [], # Saturday — выходной
6: [], # Sunday — выходной
}
def load_schedule_from_json(file_path: str | Path = BASE_DIR / "Schedule.json") -> dict[int, list[tuple[time, time, int | None]]]:
path = Path(file_path)
if not path.is_absolute():
path = BASE_DIR / path
with path.open("r", encoding="utf-8") as f:
try:
raw_data = json.load(f)
except json.JSONDecodeError as exc:
raise ValueError(f"Invalid JSON in schedule file {path}: {exc}") from exc
if not isinstance(raw_data, dict):
raise ValueError(f"Schedule JSON root must be an object, got: {type(raw_data).__name__}")
formatted_schedule: dict[int, list[tuple[time, time, int | None]]] = {day: [] for day in range(7)}
for day_key, lessons in raw_data.items():
try:
day = int(day_key)
except (TypeError, ValueError) as exc:
raise ValueError(f"Day key must be an integer from 0 to 6, got: {day_key!r}") from exc
if day < 0 or day > 6:
raise ValueError(f"Day key must be in range 0..6, got: {day}")
if not isinstance(lessons, list):
raise ValueError(f"Lessons for day {day} must be a list, got: {type(lessons).__name__}")
parsed_lessons: list[tuple[time, time, int | None]] = []
for idx, lesson in enumerate(lessons):
if not isinstance(lesson, list) or len(lesson) != 5:
raise ValueError(
f"Day {day}, lesson #{idx + 1} must be [start_h, start_m, end_h, end_m, break_minutes]"
)
start_h = _ensure_int(lesson[0], "start_h", day, idx)
start_m = _ensure_int(lesson[1], "start_m", day, idx)
end_h = _ensure_int(lesson[2], "end_h", day, idx)
end_m = _ensure_int(lesson[3], "end_m", day, idx)
break_minutes_raw = lesson[4]
if break_minutes_raw is None:
break_minutes = None
else:
break_minutes = _ensure_int(break_minutes_raw, "break_minutes", day, idx)
if break_minutes < 0:
raise ValueError(f"Day {day}, lesson #{idx + 1}: break_minutes must be >= 0")
try:
start_t = time(start_h, start_m)
end_t = time(end_h, end_m)
except ValueError as exc:
raise ValueError(f"Day {day}, lesson #{idx + 1}: invalid lesson time") from exc
if (end_h, end_m) <= (start_h, start_m):
raise ValueError(f"Day {day}, lesson #{idx + 1}: end time must be after start time")
parsed_lessons.append((start_t, end_t, break_minutes))
parsed_lessons.sort(key=lambda item: (item[0].hour, item[0].minute))
formatted_schedule[day] = parsed_lessons
return formatted_schedule
# Теперь заменяем глобальный словарь SCHEDULE:
SCHEDULE = load_schedule_from_json()
def minutes_until_break(now: datetime | None = None) -> str:
@ -364,7 +391,6 @@ async def handle_gen_mem(message: Message, bot: Bot):
await message.reply_photo(BufferedInputFile(output.getvalue(), filename="meme.jpg"))
<<<<<<< HEAD
async def handle_size(message: Message):
size = round(random.uniform(0.1, 35.0), 1)
@ -385,8 +411,7 @@ async def handle_size(message: Message):
f"📏 Твой хуек: {size} см\n"
f"Ты: {status}"
)
=======
KEYWORDS = {'крип', 'радиохэд', 'creep', 'radiohead'}
KEYWORDS_CREEP = {'крип', 'радиохэд', 'creep', 'radiohead'}
# I'M CREEP
async def handle_keywords(message: types.Message):
@ -395,7 +420,7 @@ async def handle_keywords(message: types.Message):
text = message.text.lower()
if any(re.search(rf'\b{word}\b', text) for word in KEYWORDS):
if any(re.search(rf'\b{word}\b', text) for word in KEYWORDS_CREEP):
audio_path = BASE_DIR / "maket" / "Radiohead - Creep.mp3"
if audio_path.exists():
@ -405,7 +430,6 @@ async def handle_keywords(message: types.Message):
)
else:
logger.warning(f"Файл не найден по пути: {audio_path}")
>>>>>>> SUDOZOVCHIK-CREEP-FUNCTION
def main():