forked from zovos/bot_tg
Compare commits
1 commit
07f6efe7b1
...
100fbf7051
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
100fbf7051 |
2 changed files with 141 additions and 137 deletions
105
config.py
Normal file
105
config.py
Normal file
|
|
@ -0,0 +1,105 @@
|
||||||
|
# ВСЕ КОНСТАНТНЫЕ ЗНАЧЕНИЯ
|
||||||
|
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
from datetime import timedelta, time
|
||||||
|
|
||||||
|
def make_time(h: int, m: int) -> time:
|
||||||
|
return time(hour=h, minute=m)
|
||||||
|
|
||||||
|
# Базовые пути
|
||||||
|
BASE_DIR = Path(__file__).resolve().parent
|
||||||
|
FONT_PATH = BASE_DIR / "impact.ttf"
|
||||||
|
DEFAULT_TZ = os.getenv("TZ", "Europe/Moscow")
|
||||||
|
|
||||||
|
# Состояние мини-игры
|
||||||
|
PENIS_STATE: dict[int, dict[str, object]] = {}
|
||||||
|
PENIS_START_LENGTH = 10.0
|
||||||
|
PENIS_MIN_DELTA = 0.1
|
||||||
|
PENIS_MAX_DELTA = 7.0
|
||||||
|
PENIS_COOLDOWN = timedelta(hours=24)
|
||||||
|
PENIS_TOP_LIMIT = 10
|
||||||
|
|
||||||
|
# Твои шаблоны и тот самый огромный кортеж
|
||||||
|
TEMPLATES = {
|
||||||
|
"1": {
|
||||||
|
"path": BASE_DIR / "maket" / "1.png",
|
||||||
|
"anchor": (104, 240),
|
||||||
|
"padding": 20,
|
||||||
|
"label": "Владимир Владимирович Путин самый лучший президент",
|
||||||
|
},
|
||||||
|
# Сюда вставь весь остальной огромный массив
|
||||||
|
}
|
||||||
|
|
||||||
|
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 — выходной
|
||||||
|
}
|
||||||
|
|
||||||
|
# Ключевые слова, на которые бот кидает трек Creep.
|
||||||
|
KEYWORDS = {'крип', 'радиохэд', 'creep', 'radiohead'}
|
||||||
|
|
||||||
|
|
||||||
|
def templates_list_text() -> str:
|
||||||
|
parts = []
|
||||||
|
for tid in sorted(TEMPLATES.keys()):
|
||||||
|
label = TEMPLATES[tid].get("label", "")
|
||||||
|
if label:
|
||||||
|
parts.append(f"{tid} — {label}")
|
||||||
|
else:
|
||||||
|
parts.append(tid)
|
||||||
|
return ", ".join(parts) if parts else "нет макетов"
|
||||||
|
|
||||||
|
|
||||||
|
HINT_TEXT = (
|
||||||
|
# Общая подсказка по командам.
|
||||||
|
"Команды:\n"
|
||||||
|
f"• /maket «id» «текст» — доступные: {templates_list_text()} (1: 737x414, точка 104,240).\n"
|
||||||
|
"• /gen_mem Up:верх Down:низ — отправь с фото (как подпись) или ответом на фото.\n"
|
||||||
|
"• /break — узнать, сколько минут до перекура.\n"
|
||||||
|
"• /penis — миниигра: +/− от 0.1 до 7 см, раз в 24 часа.\n"
|
||||||
|
"• /top_penis — динамический топ по текущей длине.\n"
|
||||||
|
"• /talk [сообщение] — побазарить с ИИ на фене.\n"
|
||||||
|
"• /prices — старый способ цен.\n"
|
||||||
|
"• /fetch — свежие цены с x-server.\n"
|
||||||
|
"Подсказка: в группах команда должна быть слитно с ботом (/gen_mem@username)."
|
||||||
|
)
|
||||||
173
main.py
173
main.py
|
|
@ -1,126 +1,40 @@
|
||||||
import asyncio
|
# Сделал чуть компактнее и читабельнее
|
||||||
from AI.talk_handler import handle_talk
|
import asyncio, logging, os, re, requests, random
|
||||||
import logging
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
import requests
|
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from textwrap import wrap
|
from textwrap import wrap
|
||||||
import random
|
from datetime import datetime, time, timedelta
|
||||||
|
from zoneinfo import ZoneInfo
|
||||||
|
|
||||||
from aiogram import Bot, Dispatcher, F, types
|
from aiogram import Bot, Dispatcher, F, types
|
||||||
from aiogram.enums import ParseMode
|
from aiogram.enums import ParseMode
|
||||||
from aiogram.filters import Command, CommandStart
|
from aiogram.filters import Command, CommandStart
|
||||||
from aiogram.types import BufferedInputFile, Message, BotCommand, FSInputFile
|
from aiogram.types import BufferedInputFile, Message, BotCommand, FSInputFile
|
||||||
from aiogram.client.default import DefaultBotProperties
|
from aiogram.client.default import DefaultBotProperties
|
||||||
|
|
||||||
from PIL import Image, ImageDraw, ImageFont
|
from PIL import Image, ImageDraw, ImageFont
|
||||||
from datetime import datetime, time, timedelta
|
from AI.talk_handler import handle_talk
|
||||||
from zoneinfo import ZoneInfo
|
|
||||||
|
|
||||||
# Базовые пути/настройки проекта.
|
# Конфигурационный файл, куда я вынес все константы
|
||||||
BASE_DIR = Path(__file__).parent
|
import config
|
||||||
FONT_PATH = BASE_DIR / "impact.ttf"
|
|
||||||
DEFAULT_TZ = os.getenv("TZ", "Europe/Moscow")
|
|
||||||
|
|
||||||
# In-memory состояние миниигры /penis.
|
|
||||||
# Важно: после перезапуска процесса всё обнуляется.
|
|
||||||
PENIS_STATE: dict[int, dict[str, object]] = {}
|
|
||||||
PENIS_START_LENGTH = 10.0
|
|
||||||
PENIS_MIN_DELTA = 0.1
|
|
||||||
PENIS_MAX_DELTA = 7.0
|
|
||||||
PENIS_COOLDOWN = timedelta(hours=24)
|
|
||||||
PENIS_TOP_LIMIT = 10
|
|
||||||
|
|
||||||
# Конфигурация текстовых макетов /maket.
|
|
||||||
TEMPLATES = {
|
|
||||||
"1": {
|
|
||||||
"path": BASE_DIR / "maket" / "1.png",
|
|
||||||
"anchor": (104, 240),
|
|
||||||
"padding": 20, # right/bottom padding from edges
|
|
||||||
"label": "Владимир Владимирович Путин самый лучший президент",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
def templates_list_text() -> str:
|
|
||||||
# Собираем человекочитаемый список доступных макетов.
|
|
||||||
parts = []
|
|
||||||
for tid in sorted(TEMPLATES.keys()):
|
|
||||||
label = TEMPLATES[tid].get("label", "")
|
|
||||||
if label:
|
|
||||||
parts.append(f"{tid} — {label}")
|
|
||||||
else:
|
|
||||||
parts.append(tid)
|
|
||||||
return ", ".join(parts) if parts else "нет макетов"
|
|
||||||
|
|
||||||
# ---- Schedule & breaks ----
|
# ---- Schedule & breaks ----
|
||||||
|
|
||||||
def make_time(h: int, m: int) -> time:
|
|
||||||
# Короткий хелпер для заполнения расписания.
|
|
||||||
return time(hour=h, minute=m)
|
|
||||||
|
|
||||||
|
|
||||||
# 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 minutes_until_break(now: datetime | None = None) -> str:
|
def minutes_until_break(now: datetime | None = None) -> str:
|
||||||
# Возвращает статус: до перекура / идёт перекур / пары окончены.
|
# Возвращает статус: до перекура / идёт перекур / пары окончены.
|
||||||
if now is None:
|
if now is None:
|
||||||
now = datetime.now(ZoneInfo(DEFAULT_TZ))
|
now = datetime.now(ZoneInfo(config.DEFAULT_TZ))
|
||||||
elif now.tzinfo is None:
|
elif now.tzinfo is None:
|
||||||
now = now.replace(tzinfo=ZoneInfo(DEFAULT_TZ))
|
now = now.replace(tzinfo=ZoneInfo(config.DEFAULT_TZ))
|
||||||
day = now.weekday()
|
day = now.weekday()
|
||||||
today_schedule = SCHEDULE.get(day, [])
|
today_SCHEDULE = config.SCHEDULE.get(day, [])
|
||||||
if not today_schedule:
|
if not today_SCHEDULE:
|
||||||
return "Сегодня кайфуем дома, перекур не нужен."
|
return "Сегодня кайфуем дома, перекур не нужен."
|
||||||
|
|
||||||
def dt_for(t: time) -> datetime:
|
def dt_for(t: time) -> datetime:
|
||||||
return now.replace(hour=t.hour, minute=t.minute, second=0, microsecond=0)
|
return now.replace(hour=t.hour, minute=t.minute, second=0, microsecond=0)
|
||||||
|
|
||||||
for start_t, end_t, br_minutes in today_schedule:
|
for start_t, end_t, br_minutes in today_SCHEDULE:
|
||||||
start_dt = dt_for(start_t)
|
start_dt = dt_for(start_t)
|
||||||
end_dt = dt_for(end_t)
|
end_dt = dt_for(end_t)
|
||||||
|
|
||||||
|
|
@ -143,19 +57,6 @@ def minutes_until_break(now: datetime | None = None) -> str:
|
||||||
|
|
||||||
return "Пары закончились, перекур только завтра."
|
return "Пары закончились, перекур только завтра."
|
||||||
|
|
||||||
HINT_TEXT = (
|
|
||||||
# Общая подсказка по командам.
|
|
||||||
"Команды:\n"
|
|
||||||
f"• /maket «id» «текст» — доступные: {templates_list_text()} (1: 737x414, точка 104,240).\n"
|
|
||||||
"• /gen_mem Up:верх Down:низ — отправь с фото (как подпись) или ответом на фото.\n"
|
|
||||||
"• /break — узнать, сколько минут до перекура.\n"
|
|
||||||
"• /penis — миниигра: +/− от 0.1 до 7 см, раз в 24 часа.\n"
|
|
||||||
"• /top_penis — динамический топ по текущей длине.\n"
|
|
||||||
"• /talk [сообщение] — побазарить с ИИ на фене.\n"
|
|
||||||
"• /prices — старый способ цен.\n"
|
|
||||||
"• /fetch — свежие цены с x-server.\n"
|
|
||||||
"Подсказка: в группах команда должна быть слитно с ботом (/gen_mem@username)."
|
|
||||||
)
|
|
||||||
|
|
||||||
logging.basicConfig(level=logging.INFO)
|
logging.basicConfig(level=logging.INFO)
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
@ -163,9 +64,9 @@ logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
def load_font(size: int) -> ImageFont.FreeTypeFont:
|
def load_font(size: int) -> ImageFont.FreeTypeFont:
|
||||||
# Грузим Impact нужного размера.
|
# Грузим Impact нужного размера.
|
||||||
if not FONT_PATH.exists():
|
if not config.FONT_PATH.exists():
|
||||||
raise FileNotFoundError("impact.ttf not found. Place the font in the project root.")
|
raise FileNotFoundError("impact.ttf not found. Place the font in the project root.")
|
||||||
return ImageFont.truetype(str(FONT_PATH), size=size)
|
return ImageFont.truetype(str(config.FONT_PATH), size=size)
|
||||||
|
|
||||||
|
|
||||||
def wrap_text_to_width(text: str, font: ImageFont.FreeTypeFont, max_width: int, draw: ImageDraw.ImageDraw, stroke_width: int) -> list[str]:
|
def wrap_text_to_width(text: str, font: ImageFont.FreeTypeFont, max_width: int, draw: ImageDraw.ImageDraw, stroke_width: int) -> list[str]:
|
||||||
|
|
@ -228,7 +129,7 @@ def draw_multiline(draw: ImageDraw.ImageDraw, lines: list[str], position: tuple[
|
||||||
|
|
||||||
def generate_maket(text: str, template_id: str = "1") -> BytesIO:
|
def generate_maket(text: str, template_id: str = "1") -> BytesIO:
|
||||||
# Генерируем картинку макета с текстом в заранее заданной области.
|
# Генерируем картинку макета с текстом в заранее заданной области.
|
||||||
tpl = TEMPLATES.get(template_id)
|
tpl = config.TEMPLATES.get(template_id)
|
||||||
if not tpl:
|
if not tpl:
|
||||||
raise FileNotFoundError(f"Template {template_id} is missing")
|
raise FileNotFoundError(f"Template {template_id} is missing")
|
||||||
template_path = tpl["path"]
|
template_path = tpl["path"]
|
||||||
|
|
@ -327,9 +228,9 @@ def minutes_until_next_lesson(now: datetime | None = None) -> str:
|
||||||
import random
|
import random
|
||||||
|
|
||||||
if now is None:
|
if now is None:
|
||||||
now = datetime.now(ZoneInfo(DEFAULT_TZ))
|
now = datetime.now(ZoneInfo(config.DEFAULT_TZ))
|
||||||
elif now.tzinfo is None:
|
elif now.tzinfo is None:
|
||||||
now = now.replace(tzinfo=ZoneInfo(DEFAULT_TZ))
|
now = now.replace(tzinfo=ZoneInfo(config.DEFAULT_TZ))
|
||||||
|
|
||||||
LESSON_DAYS = [1, 3] # 1 = вторник, 3 = четверг
|
LESSON_DAYS = [1, 3] # 1 = вторник, 3 = четверг
|
||||||
LESSON_START = time(9, 50)
|
LESSON_START = time(9, 50)
|
||||||
|
|
@ -400,14 +301,14 @@ def minutes_until_next_lesson(now: datetime | None = None) -> str:
|
||||||
def play_penis(user_id: int, user_name: str | None = None, now: datetime | None = None) -> tuple[bool, str]:
|
def play_penis(user_id: int, user_name: str | None = None, now: datetime | None = None) -> tuple[bool, str]:
|
||||||
# Миниигра /penis: изменение длины и кулдаун 24 часа от последнего броска.
|
# Миниигра /penis: изменение длины и кулдаун 24 часа от последнего броска.
|
||||||
if now is None:
|
if now is None:
|
||||||
now = datetime.now(ZoneInfo(DEFAULT_TZ))
|
now = datetime.now(ZoneInfo(config.DEFAULT_TZ))
|
||||||
elif now.tzinfo is None:
|
elif now.tzinfo is None:
|
||||||
now = now.replace(tzinfo=ZoneInfo(DEFAULT_TZ))
|
now = now.replace(tzinfo=ZoneInfo(config.DEFAULT_TZ))
|
||||||
|
|
||||||
state = PENIS_STATE.get(user_id)
|
state = config.PENIS_STATE.get(user_id)
|
||||||
if state is None:
|
if state is None:
|
||||||
state = {"length": PENIS_START_LENGTH, "last_used_at": None}
|
state = {"length": config.PENIS_START_LENGTH, "last_used_at": None}
|
||||||
PENIS_STATE[user_id] = state
|
config.PENIS_STATE[user_id] = state
|
||||||
|
|
||||||
# Обновляем отображаемое имя для топа.
|
# Обновляем отображаемое имя для топа.
|
||||||
if user_name:
|
if user_name:
|
||||||
|
|
@ -415,7 +316,7 @@ def play_penis(user_id: int, user_name: str | None = None, now: datetime | None
|
||||||
|
|
||||||
last_used_at = state.get("last_used_at")
|
last_used_at = state.get("last_used_at")
|
||||||
if isinstance(last_used_at, datetime):
|
if isinstance(last_used_at, datetime):
|
||||||
next_time = last_used_at + PENIS_COOLDOWN
|
next_time = last_used_at + config.PENIS_COOLDOWN
|
||||||
if now < next_time:
|
if now < next_time:
|
||||||
# Если рано, считаем оставшееся время до следующей попытки.
|
# Если рано, считаем оставшееся время до следующей попытки.
|
||||||
left = next_time - now
|
left = next_time - now
|
||||||
|
|
@ -424,8 +325,8 @@ def play_penis(user_id: int, user_name: str | None = None, now: datetime | None
|
||||||
minutes = (total_seconds % 3600) // 60
|
minutes = (total_seconds % 3600) // 60
|
||||||
return False, f"Сегодня уже кидал. Попробуй через {hours} ч {minutes} мин."
|
return False, f"Сегодня уже кидал. Попробуй через {hours} ч {minutes} мин."
|
||||||
|
|
||||||
current_length = float(state.get("length", PENIS_START_LENGTH))
|
current_length = float(state.get("length", config.PENIS_START_LENGTH))
|
||||||
delta = round(random.uniform(PENIS_MIN_DELTA, PENIS_MAX_DELTA), 1)
|
delta = round(random.uniform(config.PENIS_MIN_DELTA, config.PENIS_MAX_DELTA), 1)
|
||||||
sign = random.choice([-1, 1])
|
sign = random.choice([-1, 1])
|
||||||
# Не даём длине уйти в отрицательные значения.
|
# Не даём длине уйти в отрицательные значения.
|
||||||
new_length = round(max(0.1, current_length + sign * delta), 1)
|
new_length = round(max(0.1, current_length + sign * delta), 1)
|
||||||
|
|
@ -451,10 +352,10 @@ def format_penis_user_name(user: types.User) -> str:
|
||||||
return f"user_{user.id}"
|
return f"user_{user.id}"
|
||||||
|
|
||||||
|
|
||||||
def build_penis_top(limit: int = PENIS_TOP_LIMIT) -> str:
|
def build_penis_top(limit: int = config.PENIS_TOP_LIMIT) -> str:
|
||||||
# Формируем динамический топ по текущим значениям /penis.
|
# Формируем динамический топ по текущим значениям /penis.
|
||||||
rows: list[tuple[float, str]] = []
|
rows: list[tuple[float, str]] = []
|
||||||
for user_id, state in PENIS_STATE.items():
|
for user_id, state in config.PENIS_STATE.items():
|
||||||
length = state.get("length")
|
length = state.get("length")
|
||||||
if not isinstance(length, (int, float)):
|
if not isinstance(length, (int, float)):
|
||||||
continue
|
continue
|
||||||
|
|
@ -481,7 +382,7 @@ async def handle_start(message: Message):
|
||||||
|
|
||||||
async def handle_help(message: Message):
|
async def handle_help(message: Message):
|
||||||
# Вывод подсказки по возможностям бота.
|
# Вывод подсказки по возможностям бота.
|
||||||
await message.answer(HINT_TEXT)
|
await message.answer(config.HINT_TEXT)
|
||||||
|
|
||||||
async def handle_break(message: Message):
|
async def handle_break(message: Message):
|
||||||
# Команда расписания перекура.
|
# Команда расписания перекура.
|
||||||
|
|
@ -492,14 +393,14 @@ async def handle_maket(message: Message):
|
||||||
# Генерация текста в подготовленном шаблоне /maket.
|
# Генерация текста в подготовленном шаблоне /maket.
|
||||||
parts = message.text.split(maxsplit=2)
|
parts = message.text.split(maxsplit=2)
|
||||||
if len(parts) == 1:
|
if len(parts) == 1:
|
||||||
await message.reply(f"Доступные макеты: {templates_list_text()}\nФормат: /maket «id» «текст»")
|
await message.reply(f"Доступные макеты: {config.templates_list_text()}\nФормат: /maket «id» «текст»")
|
||||||
return
|
return
|
||||||
if len(parts) < 3:
|
if len(parts) < 3:
|
||||||
await message.reply(f"Формат: /maket «id» «текст»\nДоступные макеты: {templates_list_text()}\n\n" + HINT_TEXT)
|
await message.reply(f"Формат: /maket «id» «текст»\nДоступные макеты: {config.templates_list_text()}\n\n" + config.HINT_TEXT)
|
||||||
return
|
return
|
||||||
template_id = parts[1]
|
template_id = parts[1]
|
||||||
if template_id not in TEMPLATES:
|
if template_id not in config.TEMPLATES:
|
||||||
await message.reply(f"Такого макета нет. Доступные: {templates_list_text()}")
|
await message.reply(f"Такого макета нет. Доступные: {config.templates_list_text()}")
|
||||||
return
|
return
|
||||||
text = parts[2].strip()
|
text = parts[2].strip()
|
||||||
if not text:
|
if not text:
|
||||||
|
|
@ -592,9 +493,7 @@ async def handle_top_penis(message: Message):
|
||||||
await message.answer(build_penis_top())
|
await message.answer(build_penis_top())
|
||||||
|
|
||||||
|
|
||||||
# Ключевые слова, на которые бот кидает трек Creep.
|
# Смотреть config.py
|
||||||
KEYWORDS = {'крип', 'радиохэд', 'creep', 'radiohead'}
|
|
||||||
# I'M CREEP
|
|
||||||
async def handle_keywords(message: types.Message):
|
async def handle_keywords(message: types.Message):
|
||||||
# Не реагируем на команды, только на обычный текст.
|
# Не реагируем на команды, только на обычный текст.
|
||||||
|
|
||||||
|
|
@ -603,8 +502,8 @@ 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 config.KEYWORDS):
|
||||||
audio_path = BASE_DIR / "maket" / "Radiohead - Creep.mp3"
|
audio_path = config.BASE_DIR / "maket" / "Radiohead - Creep.mp3"
|
||||||
|
|
||||||
if audio_path.exists():
|
if audio_path.exists():
|
||||||
await message.answer_audio(
|
await message.answer_audio(
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue