forked from zovos/bot_tg
Ну насрал, ну уебан, короче jsonchik запилил, и сделал супер безопасный парсер этого json, хотя лучше энивей потом перейти на бд
This commit is contained in:
parent
11ad1c43c9
commit
e0a46cf551
2 changed files with 119 additions and 52 deletions
43
Schedule.json
Normal file
43
Schedule.json
Normal 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
128
main.py
|
|
@ -1,11 +1,12 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from textwrap import wrap
|
|
||||||
import random
|
import random
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
from aiogram import Bot, Dispatcher, F, types
|
from aiogram import Bot, Dispatcher, F, types
|
||||||
from aiogram.enums import ParseMode
|
from aiogram.enums import ParseMode
|
||||||
|
|
@ -40,54 +41,80 @@ def templates_list_text() -> str:
|
||||||
|
|
||||||
# ---- Schedule & breaks ----
|
# ---- Schedule & breaks ----
|
||||||
|
|
||||||
def make_time(h: int, m: int) -> time:
|
def _ensure_int(value: Any, field_name: str, day: int, lesson_idx: int) -> int:
|
||||||
return time(hour=h, minute=m)
|
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)
|
def load_schedule_from_json(file_path: str | Path = BASE_DIR / "Schedule.json") -> dict[int, list[tuple[time, time, int | None]]]:
|
||||||
SCHEDULE: dict[int, list[tuple[time, time, int | None]]] = {
|
path = Path(file_path)
|
||||||
0: [ # Monday
|
if not path.is_absolute():
|
||||||
(make_time(9, 50), make_time(10, 35), 5),
|
path = BASE_DIR / path
|
||||||
(make_time(10, 40), make_time(11, 25), 30),
|
|
||||||
(make_time(11, 55), make_time(12, 40), 5),
|
with path.open("r", encoding="utf-8") as f:
|
||||||
(make_time(12, 45), make_time(13, 30), 15),
|
try:
|
||||||
(make_time(13, 45), make_time(14, 30), 5),
|
raw_data = json.load(f)
|
||||||
(make_time(14, 35), make_time(15, 20), 30),
|
except json.JSONDecodeError as exc:
|
||||||
(make_time(15, 50), make_time(16, 35), 5),
|
raise ValueError(f"Invalid JSON in schedule file {path}: {exc}") from exc
|
||||||
(make_time(16, 40), make_time(17, 25), None),
|
|
||||||
],
|
if not isinstance(raw_data, dict):
|
||||||
1: [ # Tuesday
|
raise ValueError(f"Schedule JSON root must be an object, got: {type(raw_data).__name__}")
|
||||||
(make_time(9, 50), make_time(10, 35), 5),
|
|
||||||
(make_time(10, 40), make_time(11, 25), 30),
|
formatted_schedule: dict[int, list[tuple[time, time, int | None]]] = {day: [] for day in range(7)}
|
||||||
(make_time(11, 55), make_time(12, 40), 5),
|
|
||||||
(make_time(12, 45), make_time(13, 30), 15),
|
for day_key, lessons in raw_data.items():
|
||||||
(make_time(13, 45), make_time(14, 30), 5),
|
try:
|
||||||
(make_time(14, 35), make_time(15, 20), None),
|
day = int(day_key)
|
||||||
],
|
except (TypeError, ValueError) as exc:
|
||||||
2: [], # Wednesday — кайфуем дома
|
raise ValueError(f"Day key must be an integer from 0 to 6, got: {day_key!r}") from exc
|
||||||
3: [ # Thursday
|
|
||||||
(make_time(8, 0), make_time(8, 45), 5),
|
if day < 0 or day > 6:
|
||||||
(make_time(8, 50), make_time(9, 35), 15),
|
raise ValueError(f"Day key must be in range 0..6, got: {day}")
|
||||||
(make_time(9, 50), make_time(10, 35), 5),
|
|
||||||
(make_time(10, 40), make_time(11, 25), 30),
|
if not isinstance(lessons, list):
|
||||||
(make_time(11, 55), make_time(12, 40), 5),
|
raise ValueError(f"Lessons for day {day} must be a list, got: {type(lessons).__name__}")
|
||||||
(make_time(12, 45), make_time(13, 30), 15),
|
|
||||||
(make_time(13, 45), make_time(14, 30), 5),
|
parsed_lessons: list[tuple[time, time, int | None]] = []
|
||||||
(make_time(14, 35), make_time(15, 20), 30),
|
for idx, lesson in enumerate(lessons):
|
||||||
(make_time(15, 50), make_time(16, 35), 5),
|
if not isinstance(lesson, list) or len(lesson) != 5:
|
||||||
(make_time(16, 40), make_time(17, 25), None),
|
raise ValueError(
|
||||||
],
|
f"Day {day}, lesson #{idx + 1} must be [start_h, start_m, end_h, end_m, break_minutes]"
|
||||||
4: [ # Friday
|
)
|
||||||
(make_time(9, 50), make_time(10, 35), 5),
|
|
||||||
(make_time(10, 40), make_time(11, 25), 30),
|
start_h = _ensure_int(lesson[0], "start_h", day, idx)
|
||||||
(make_time(11, 55), make_time(12, 40), 5),
|
start_m = _ensure_int(lesson[1], "start_m", day, idx)
|
||||||
(make_time(12, 45), make_time(13, 30), 15),
|
end_h = _ensure_int(lesson[2], "end_h", day, idx)
|
||||||
(make_time(13, 45), make_time(14, 30), 5),
|
end_m = _ensure_int(lesson[3], "end_m", day, idx)
|
||||||
(make_time(14, 35), make_time(15, 20), None),
|
|
||||||
],
|
break_minutes_raw = lesson[4]
|
||||||
5: [], # Saturday — выходной
|
if break_minutes_raw is None:
|
||||||
6: [], # Sunday — выходной
|
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:
|
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"))
|
await message.reply_photo(BufferedInputFile(output.getvalue(), filename="meme.jpg"))
|
||||||
|
|
||||||
<<<<<<< HEAD
|
|
||||||
async def handle_size(message: Message):
|
async def handle_size(message: Message):
|
||||||
size = round(random.uniform(0.1, 35.0), 1)
|
size = round(random.uniform(0.1, 35.0), 1)
|
||||||
|
|
||||||
|
|
@ -385,8 +411,7 @@ async def handle_size(message: Message):
|
||||||
f"📏 Твой хуек: {size} см\n"
|
f"📏 Твой хуек: {size} см\n"
|
||||||
f"Ты: {status}"
|
f"Ты: {status}"
|
||||||
)
|
)
|
||||||
=======
|
KEYWORDS_CREEP = {'крип', 'радиохэд', 'creep', 'radiohead'}
|
||||||
KEYWORDS = {'крип', 'радиохэд', 'creep', 'radiohead'}
|
|
||||||
# I'M CREEP
|
# I'M CREEP
|
||||||
async def handle_keywords(message: types.Message):
|
async def handle_keywords(message: types.Message):
|
||||||
|
|
||||||
|
|
@ -395,7 +420,7 @@ async def handle_keywords(message: types.Message):
|
||||||
|
|
||||||
text = message.text.lower()
|
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"
|
audio_path = BASE_DIR / "maket" / "Radiohead - Creep.mp3"
|
||||||
|
|
||||||
if audio_path.exists():
|
if audio_path.exists():
|
||||||
|
|
@ -405,7 +430,6 @@ async def handle_keywords(message: types.Message):
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
logger.warning(f"Файл не найден по пути: {audio_path}")
|
logger.warning(f"Файл не найден по пути: {audio_path}")
|
||||||
>>>>>>> SUDOZOVCHIK-CREEP-FUNCTION
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue