типо да
This commit is contained in:
15
bot/handlers/__init__.py
Normal file
15
bot/handlers/__init__.py
Normal file
@@ -0,0 +1,15 @@
|
||||
from aiogram import Router
|
||||
#from .commands import router as cmd_routers
|
||||
from .messages import router as messages_routers
|
||||
from .secret import router as secret_routers
|
||||
|
||||
# Настройка экспорта и роутера
|
||||
__all__ = ("router",)
|
||||
router: Router = Router(name=__name__)
|
||||
|
||||
# Подключение роутеров
|
||||
router.include_routers(
|
||||
#cmd_routers,
|
||||
secret_routers,
|
||||
messages_routers,
|
||||
)
|
||||
13
bot/handlers/commands/__init__.py
Normal file
13
bot/handlers/commands/__init__.py
Normal file
@@ -0,0 +1,13 @@
|
||||
from aiogram import Router
|
||||
from .admins import router as admin_cmd_router
|
||||
from .users import router as users_cmd_router
|
||||
|
||||
# Настройка экспорта и роутера
|
||||
__all__ = ("router",)
|
||||
router: Router = Router(name=__name__)
|
||||
|
||||
# Подключение роутеров
|
||||
router.include_routers(
|
||||
admin_cmd_router,
|
||||
users_cmd_router,
|
||||
)
|
||||
11
bot/handlers/commands/admins/__init__.py
Normal file
11
bot/handlers/commands/admins/__init__.py
Normal file
@@ -0,0 +1,11 @@
|
||||
from aiogram import Router
|
||||
from .settings_cmd import router as settings_cmd_router
|
||||
|
||||
# Настройка экспорта и роутера
|
||||
__all__ = ("router",)
|
||||
router: Router = Router(name=__name__)
|
||||
|
||||
# Подключение роутеров
|
||||
router.include_routers(
|
||||
settings_cmd_router,
|
||||
)
|
||||
51
bot/handlers/commands/admins/settings_cmd.py
Normal file
51
bot/handlers/commands/admins/settings_cmd.py
Normal file
@@ -0,0 +1,51 @@
|
||||
from aiogram import Router, F
|
||||
from aiogram.filters import Command
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from aiogram.types import Message, CallbackQuery, InlineKeyboardButton
|
||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||
from aiogram.utils.i18n import gettext as _
|
||||
|
||||
from bot.templates import msg_photo
|
||||
from bot.utils.interesting_facts import interesting_fact
|
||||
from bot.core.bots import BotInfo
|
||||
from configs import COMMANDS, RpValue
|
||||
|
||||
# Настройки экспорта и роутера
|
||||
__all__ = ("router",)
|
||||
CMD: str = "settings".lower()
|
||||
router: Router = Router(name=f"{CMD}_cmd_router")
|
||||
|
||||
|
||||
@router.callback_query(F.data.lower() == CMD)
|
||||
@router.message(Command(*COMMANDS[CMD], prefix=BotInfo.prefix, ignore_case=True))
|
||||
async def start_cmd(message: Message | CallbackQuery, state: FSMContext) -> None:
|
||||
"""Обработчик команды /start"""
|
||||
await state.clear()
|
||||
|
||||
# Создание инлайн-клавиатуры
|
||||
ikb: InlineKeyboardBuilder = InlineKeyboardBuilder()
|
||||
ikb.row(InlineKeyboardButton(text="Инфо-канал🗂", url=RpValue.INFO_URL))
|
||||
ikb.row(InlineKeyboardButton(text="Вступление🚀", callback_data='new'),
|
||||
InlineKeyboardButton(text="Анкета📖", callback_data='anketa'))
|
||||
ikb.row(InlineKeyboardButton(text="Связь с администрацией🌐", callback_data='admin'))
|
||||
|
||||
# Формируем приветственное сообщение
|
||||
text: str = _(
|
||||
"""Добро пожаловать, <a href="{url}">{name}</a>!
|
||||
|
||||
Я ваш искусственный помощник по ролевой - <b>{rp_name}</b>!
|
||||
Моя цель — помочь вам сориентироваться и сделать ваше вступление куда проще!
|
||||
Надеюсь, я смогу вам помочь! Пожалуйста, выберите нужную функцию на клавиатуре!
|
||||
|
||||
Интересный факт:
|
||||
<blockquote>{fact}</blockquote>
|
||||
"""
|
||||
).format(
|
||||
url=message.from_user.url if message.from_user else "",
|
||||
name=message.from_user.first_name if message.from_user else "пользователь",
|
||||
rp_name=RpValue.RP_NAME,
|
||||
fact=interesting_fact(),
|
||||
)
|
||||
|
||||
# Отправляем сообщение
|
||||
await msg_photo(message=message, text=text, file=f'assets/{CMD}.jpg', markup=ikb)
|
||||
13
bot/handlers/commands/users/__init__.py
Normal file
13
bot/handlers/commands/users/__init__.py
Normal file
@@ -0,0 +1,13 @@
|
||||
from aiogram import Router
|
||||
from .start_cmd import router as start_cmd_router
|
||||
from .active import router as active_cmd_router
|
||||
|
||||
# Настройка экспорта и роутера
|
||||
__all__ = ("router",)
|
||||
router: Router = Router(name=__name__)
|
||||
|
||||
# Подключение роутеров
|
||||
router.include_routers(
|
||||
start_cmd_router,
|
||||
active_cmd_router,
|
||||
)
|
||||
45
bot/handlers/commands/users/active.py
Normal file
45
bot/handlers/commands/users/active.py
Normal file
@@ -0,0 +1,45 @@
|
||||
from aiogram import Router, F
|
||||
from aiogram.filters import Command
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from aiogram.types import Message, CallbackQuery
|
||||
|
||||
from bot.templates import msg_photo
|
||||
from bot.core.bots import BotInfo
|
||||
from configs import COMMANDS
|
||||
from database import db
|
||||
|
||||
|
||||
|
||||
# Настройки экспорта и роутера
|
||||
__all__ = ("router",)
|
||||
|
||||
|
||||
CMD: str = "active".lower()
|
||||
router: Router = Router(name=f"{CMD}_cmd_router")
|
||||
|
||||
|
||||
@router.callback_query(F.data.lower() == CMD)
|
||||
@router.message(Command(*COMMANDS[CMD], prefix=BotInfo.prefix, ignore_case=True))
|
||||
async def active_cmd(message: Message | CallbackQuery, state: FSMContext) -> None:
|
||||
"""Обработчик команды /active"""
|
||||
await state.clear()
|
||||
|
||||
# Получить статистику сообщений пользователя
|
||||
day, week, month, total = await db.get_message_stats(message.from_user.id)
|
||||
|
||||
print(f"За день: {day} сообщений")
|
||||
print(f"За неделю: {week} сообщений")
|
||||
print(f"За месяц: {month} сообщений")
|
||||
print(f"Всего: {total} сообщений")
|
||||
|
||||
# Формируем приветственное сообщение
|
||||
text: str =f"""
|
||||
За день: {day} сообщений
|
||||
За неделю: {week} сообщений
|
||||
За месяц: {month} сообщений
|
||||
Всего: {total} сообщений
|
||||
"""
|
||||
|
||||
|
||||
# Отправляем сообщение
|
||||
await msg_photo(message=message, text=text,)
|
||||
0
bot/handlers/commands/users/anketa_cmd.py
Normal file
0
bot/handlers/commands/users/anketa_cmd.py
Normal file
218
bot/handlers/commands/users/new_cmd.py
Normal file
218
bot/handlers/commands/users/new_cmd.py
Normal file
@@ -0,0 +1,218 @@
|
||||
import re
|
||||
from typing import Optional, Dict, Tuple
|
||||
|
||||
from aiogram import Router, F
|
||||
from aiogram.filters import Command
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from aiogram.types import Message, CallbackQuery, InlineKeyboardButton
|
||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||
from aiogram.utils.i18n import gettext as _
|
||||
|
||||
from bot.core.bots import BotInfo
|
||||
from bot.keyboards.inline.decision import decision_keyboard
|
||||
from bot.states.new_states import NewStates
|
||||
from bot.templates import msg
|
||||
from middleware.loggers import log
|
||||
from configs import COMMANDS, ImportantID, RpValue
|
||||
|
||||
# Глобальная мапа для хранения связей пользователь-топик
|
||||
user_topic_map: Dict[Tuple[int, str], int] = {}
|
||||
|
||||
__all__ = ("router",)
|
||||
CMD: str = "new"
|
||||
router: Router = Router(name=f"{CMD}_cmd_router")
|
||||
TOPIC_TYPE: str = "anketa"
|
||||
|
||||
TEXTS: Dict[str, Dict[str, str]] = {
|
||||
"anketa": {
|
||||
"accept": f"<b>🎉 Ваша анкета принята!</b>\n\nДобро пожаловать в проект!\n\nФлуд: {RpValue.FLUD_URL}\nРолевая: {RpValue.RP_URL}",
|
||||
"reject": "<b>❌ Ваша анкета отклонена.</b>\n\nВы можете попробовать позже."
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async def validate_russian_text(text: str) -> bool:
|
||||
"""Проверяет текст на соответствие русским буквам, пробелам и дефисам."""
|
||||
return bool(re.fullmatch(r"[А-Яа-яЁё\s\-]+", text))
|
||||
|
||||
|
||||
# ===================== Команда /new =====================
|
||||
@router.callback_query(F.data == CMD)
|
||||
@router.message(Command(*COMMANDS[CMD], prefix=BotInfo.prefix, ignore_case=True))
|
||||
@log(level='INFO', log_type=CMD.upper(), text=f"использовал команду /{CMD}")
|
||||
async def new_cmd(message: Message | CallbackQuery, state: FSMContext) -> None:
|
||||
"""
|
||||
Начало анкеты /new.
|
||||
Отправляет пользователю сообщение с просьбой указать желаемую роль.
|
||||
"""
|
||||
await state.clear()
|
||||
await state.set_state(NewStates.role)
|
||||
|
||||
ikb: InlineKeyboardBuilder = InlineKeyboardBuilder()
|
||||
ikb.row(InlineKeyboardButton(text="Отмена↩️", callback_data='start'))
|
||||
|
||||
text: str = _(
|
||||
"Пожалуйста, отправьте желаемую роль:\n"
|
||||
"(только русские буквы, пробелы или дефисы)"
|
||||
)
|
||||
|
||||
await msg(message=message, text=text, markup=ikb)
|
||||
|
||||
|
||||
# ===================== Обработка роли =====================
|
||||
@router.message(NewStates.role)
|
||||
async def process_role(message: Message, state: FSMContext) -> None:
|
||||
"""Обрабатывает ввод роли и запрашивает сортол."""
|
||||
if not await validate_russian_text(message.text):
|
||||
await message.reply("Ошибка: роль должна содержать только русские буквы, пробелы или дефисы.")
|
||||
return
|
||||
|
||||
await state.update_data(role=message.text.strip().title())
|
||||
await state.set_state(NewStates.sorol)
|
||||
|
||||
ikb: InlineKeyboardBuilder = InlineKeyboardBuilder()
|
||||
ikb.row(InlineKeyboardButton(text="Отмена↩️", callback_data='start'))
|
||||
|
||||
await message.reply(
|
||||
text="Теперь укажите желаемый сортол:\n(только русские буквы, пробелы или дефисы)",
|
||||
reply_markup=ikb.as_markup()
|
||||
)
|
||||
|
||||
|
||||
# ===================== Обработка сортола =====================
|
||||
@router.message(NewStates.sorol)
|
||||
async def process_sortol(message: Message, state: FSMContext) -> None:
|
||||
"""Обрабатывает ввод сортола и запрашивает кодовую фразу."""
|
||||
if not await validate_russian_text(message.text):
|
||||
await message.reply("Ошибка: сорол должен содержать только русские буквы, пробелы или дефисы.")
|
||||
return
|
||||
|
||||
await state.update_data(sortol=message.text.strip().title())
|
||||
await state.set_state(NewStates.code_phrase)
|
||||
|
||||
ikb: InlineKeyboardBuilder = InlineKeyboardBuilder()
|
||||
ikb.row(InlineKeyboardButton(text="Отмена↩️", callback_data='start'))
|
||||
|
||||
await message.reply(
|
||||
text="Теперь введите кодовую фразу из правил:",
|
||||
reply_markup=ikb.as_markup()
|
||||
)
|
||||
|
||||
|
||||
# ===================== Обработка кодовой фразы =====================
|
||||
@router.message(NewStates.code_phrase)
|
||||
async def process_code_phrase(message: Message, state: FSMContext) -> None:
|
||||
"""Обрабатывает ввод кодовой фразы и показывает предпросмотр анкеты."""
|
||||
code_phrase = message.text.strip()
|
||||
if not code_phrase:
|
||||
await message.reply("Кодовая фраза не может быть пустой.")
|
||||
return
|
||||
|
||||
await state.update_data(code_phrase=code_phrase)
|
||||
data: Dict[str, str] = await state.get_data()
|
||||
|
||||
ikb: InlineKeyboardBuilder = InlineKeyboardBuilder()
|
||||
ikb.row(
|
||||
InlineKeyboardButton(text="Отправить!", callback_data="submit_new"),
|
||||
InlineKeyboardButton(text="Отмена↩️", callback_data="start")
|
||||
)
|
||||
|
||||
text: str = (
|
||||
f"<b>Проверьте данные анкеты:</b>\n\n"
|
||||
f"• Роль: {data['role']}\n"
|
||||
f"• Сортол: {data['sortol']}\n"
|
||||
f"• Кодовая фраза: {data['code_phrase']}"
|
||||
)
|
||||
|
||||
await message.reply(text, reply_markup=ikb.as_markup())
|
||||
|
||||
|
||||
# ===================== Отправка анкеты в поддержку =====================
|
||||
@router.callback_query(F.data == "submit_new")
|
||||
async def submit_new_cmd(callback: CallbackQuery, state: FSMContext) -> None:
|
||||
"""Отправляет анкету в топик форума поддержки и создает запись в мапе."""
|
||||
data: Dict[str, str] = await state.get_data()
|
||||
user = callback.from_user
|
||||
|
||||
# Создаем топик в форуме
|
||||
topic = await callback.bot.create_forum_topic(
|
||||
chat_id=ImportantID.SUPPORT_CHAT_ID,
|
||||
name=f"Анкета от {user.full_name}"
|
||||
)
|
||||
thread_id: int = topic.message_thread_id
|
||||
|
||||
# Сохраняем связь пользователь-топик
|
||||
user_topic_map[(user.id, TOPIC_TYPE)] = thread_id
|
||||
|
||||
# Формируем текст анкеты
|
||||
text: str = (
|
||||
f'<b><a href="tg://user?id={user.id}">Анкета</a></b>\n\n'
|
||||
f"• Роль: {data['role']}\n"
|
||||
f"• Сортол: {data['sortol']}\n"
|
||||
f"• Кодовая фраза: {data['code_phrase']}"
|
||||
)
|
||||
|
||||
# Отправляем в топик с кнопками принятия/отклонения
|
||||
await callback.bot.send_message(
|
||||
chat_id=ImportantID.SUPPORT_CHAT_ID,
|
||||
message_thread_id=thread_id,
|
||||
text=text,
|
||||
parse_mode="HTML",
|
||||
reply_markup=decision_keyboard(thread_id=thread_id, kind=TOPIC_TYPE)
|
||||
)
|
||||
|
||||
await callback.message.edit_text("✅ Ваша анкета успешно отправлена на рассмотрение!")
|
||||
await state.clear()
|
||||
|
||||
|
||||
# ===================== Обработка решения админов =====================
|
||||
@router.callback_query(F.data.regexp(r"^([a-z_]+):(accept|reject):(\d+)$"))
|
||||
async def process_decision_callback(callback: CallbackQuery) -> None:
|
||||
"""Обрабатывает решение администраторов и отправляет результат пользователю."""
|
||||
kind, action, thread_id_str = callback.data.split(":")
|
||||
thread_id = int(thread_id_str)
|
||||
|
||||
# Ищем пользователя по thread_id в мапе
|
||||
user_id = None
|
||||
for (uid, k), tid in user_topic_map.items():
|
||||
if k == kind and tid == thread_id:
|
||||
user_id = uid
|
||||
break
|
||||
|
||||
if not user_id:
|
||||
await callback.answer("Пользователь не найден.", show_alert=True)
|
||||
return
|
||||
|
||||
text_to_send: Optional[str] = TEXTS.get(kind, {}).get(action)
|
||||
if not text_to_send:
|
||||
await callback.answer("Некорректные данные.", show_alert=True)
|
||||
return
|
||||
|
||||
await callback.bot.send_message(chat_id=user_id, text=text_to_send, parse_mode="HTML")
|
||||
await callback.message.edit_reply_markup(reply_markup=None)
|
||||
await callback.answer("Ответ отправлен пользователю.")
|
||||
|
||||
|
||||
# ===================== Пересылка ответов админов пользователю =====================
|
||||
@router.message(F.is_topic_message, F.reply_to_message, ~F.from_user.is_bot)
|
||||
async def forward_reply_to_user(message: Message) -> None:
|
||||
"""Пересылает ответы администраторов из топика пользователю."""
|
||||
thread_id = message.message_thread_id
|
||||
if not thread_id:
|
||||
return
|
||||
|
||||
# Ищем пользователя по thread_id
|
||||
user_id = None
|
||||
for (uid, _), tid in user_topic_map.items():
|
||||
if tid == thread_id:
|
||||
user_id = uid
|
||||
break
|
||||
|
||||
if not user_id:
|
||||
return
|
||||
|
||||
reply_text: str = f"<b>Ответ администратора:</b>\n{message.html_text}"
|
||||
try:
|
||||
await message.bot.send_message(chat_id=user_id, text=reply_text, parse_mode="HTML")
|
||||
except Exception as e:
|
||||
await message.reply(f"⚠️ Не удалось отправить сообщение пользователю: {e}")
|
||||
51
bot/handlers/commands/users/start_cmd.py
Normal file
51
bot/handlers/commands/users/start_cmd.py
Normal file
@@ -0,0 +1,51 @@
|
||||
from aiogram import Router, F
|
||||
from aiogram.filters import Command
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from aiogram.types import Message, CallbackQuery, InlineKeyboardButton
|
||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||
from aiogram.utils.i18n import gettext as _
|
||||
|
||||
from bot.templates import msg_photo
|
||||
from bot.utils.interesting_facts import interesting_fact
|
||||
from bot.core.bots import BotInfo
|
||||
from configs import COMMANDS, RpValue
|
||||
|
||||
# Настройки экспорта и роутера
|
||||
__all__ = ("router",)
|
||||
CMD: str = "start".lower()
|
||||
router: Router = Router(name=f"{CMD}_cmd_router")
|
||||
|
||||
|
||||
@router.callback_query(F.data.lower() == CMD)
|
||||
@router.message(Command(*COMMANDS[CMD], prefix=BotInfo.prefix, ignore_case=True))
|
||||
async def start_cmd(message: Message | CallbackQuery, state: FSMContext) -> None:
|
||||
"""Обработчик команды /start"""
|
||||
await state.clear()
|
||||
|
||||
# Создание инлайн-клавиатуры
|
||||
ikb: InlineKeyboardBuilder = InlineKeyboardBuilder()
|
||||
ikb.row(InlineKeyboardButton(text="Инфо-канал🗂", url=RpValue.INFO_URL))
|
||||
ikb.row(InlineKeyboardButton(text="Вступление🚀", callback_data='new'),
|
||||
InlineKeyboardButton(text="Анкета📖", callback_data='anketa'))
|
||||
ikb.row(InlineKeyboardButton(text="Связь с администрацией🌐", callback_data='admin'))
|
||||
|
||||
# Формируем приветственное сообщение
|
||||
text: str = _(
|
||||
"""Добро пожаловать, <a href="{url}">{name}</a>!
|
||||
|
||||
Я ваш искусственный помощник по ролевой - <b>{rp_name}</b>!
|
||||
Моя цель — помочь вам сориентироваться и сделать ваше вступление куда проще!
|
||||
Надеюсь, я смогу вам помочь! Пожалуйста, выберите нужную функцию на клавиатуре!
|
||||
|
||||
Интересный факт:
|
||||
<blockquote>{fact}</blockquote>
|
||||
"""
|
||||
).format(
|
||||
url=message.from_user.url if message.from_user else "",
|
||||
name=message.from_user.first_name if message.from_user else "пользователь",
|
||||
rp_name=RpValue.RP_NAME,
|
||||
fact=interesting_fact(),
|
||||
)
|
||||
|
||||
# Отправляем сообщение
|
||||
await msg_photo(message=message, text=text, file=f'assets/{CMD}.jpg', markup=ikb)
|
||||
15
bot/handlers/messages/__init__.py
Normal file
15
bot/handlers/messages/__init__.py
Normal file
@@ -0,0 +1,15 @@
|
||||
from aiogram import Router
|
||||
from .default import router as default_message_router
|
||||
from .reply_msg import router as reply_message_router
|
||||
|
||||
# Настройка экспорта и роутера
|
||||
__all__ = ('router',)
|
||||
router: Router = Router(name=__name__)
|
||||
|
||||
# Подготовка роутера команд
|
||||
#router.include_routers(
|
||||
#reply_message_router,
|
||||
#)
|
||||
|
||||
# Подключение стандартного роутера
|
||||
router.include_router(default_message_router)
|
||||
139
bot/handlers/messages/default.py
Normal file
139
bot/handlers/messages/default.py
Normal file
@@ -0,0 +1,139 @@
|
||||
from typing import Dict, List
|
||||
|
||||
from aiogram import Router
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from aiogram.types import Message
|
||||
|
||||
from bot.utils import get_best_response
|
||||
|
||||
|
||||
# Настройка экспорта и роутера
|
||||
__all__ = ("router",)
|
||||
router: Router = Router(name="message_router")
|
||||
|
||||
|
||||
# === Словарь ключевых слов (синонимы) и возможных ответов ===
|
||||
RESPONSES: Dict[str, Dict[str, List[str]]] = {
|
||||
"док": {
|
||||
"keywords": ["доктор", "док", "дотторе", "зандик"],
|
||||
"answers": [
|
||||
"Дотторе довольно милый друг! Мне нравится проводить с ним время!",
|
||||
"Иногда он бывает слишком суровым... Но я верю, что смогу его перевоспитать!",
|
||||
"Мне иногда кажется, что он знает больше историй, чем хранится в библиотеке!",
|
||||
"Дотторе говорит загадками... а я всё равно не всегда понимаю!",
|
||||
"Он умный, но я уверен — внутри он добрый!",
|
||||
"Дотторе иногда ворчит, но всё равно заботится обо мне по-своему!",
|
||||
"Он часто думает о науке... а я думаю о печеньках!",
|
||||
"Мне кажется, он притворяется злым, а на самом деле просто боится дружбы.",
|
||||
"Когда он работает, в комнате становится тихо... даже огонь боится мешать ему.",
|
||||
"Я иногда думаю... а улыбается ли он, когда меня не видит?",
|
||||
],
|
||||
},
|
||||
"ара": {
|
||||
"keywords": ["ара", "аранара", "аранары", "ары", "кто ты", "ты кто"],
|
||||
"answers": [
|
||||
"Мы, аранары, очень любим веселиться и смеяться!",
|
||||
"Хи-хи! 🌱 Ты можешь звать меня Ари!",
|
||||
"Наш народ живёт уже тысячи лет... но мы не умеем считать!",
|
||||
"Я маленький грибочек, но у меня большое сердце!",
|
||||
"Аранара — это хранитель улыбок и весёлых историй!",
|
||||
"Я люблю играть с детьми и рассказывать им истории!",
|
||||
"Говорят, что аранары видят то, что скрыто от других.",
|
||||
"Я — часть этой библиотеки, её дыхание и её смех!",
|
||||
"Аранара — это маленький проводник в мир грёз и чудес.",
|
||||
"Мы появляемся там, где нужен друг, даже если никто не звал!",
|
||||
],
|
||||
},
|
||||
"малыш": {
|
||||
"keywords": ["малыш", "девочка", "малышка", "она", "болезнь"],
|
||||
"answers": [
|
||||
"Она милая девочка! Жаль, что больна!",
|
||||
"Она обожает сказки! Может, именно поэтому засыпает так сладко.",
|
||||
"А как её зовут?.. Я всегда забываю спросить!",
|
||||
"Иногда во сне она улыбается... значит, ей снятся хорошие истории.",
|
||||
"Дотторе грустит, когда смотрит на неё... но я верю, он её спасёт!",
|
||||
"Она словно светильник в тёмной комнате... даже если свет её тускнеет.",
|
||||
"Я думаю, её мечты сильнее болезни.",
|
||||
],
|
||||
},
|
||||
"эфир": {
|
||||
"keywords": ["эфир", "проект", "изобретение", "сплав", "эксперимент", "ядро"],
|
||||
"answers": [
|
||||
"Эфир звучит как ветер, который нельзя поймать... но можно почувствовать!",
|
||||
"Дотторе часто говорит о проектах, но я понимаю в них только половину!",
|
||||
"Каждый новый сплав для него как новая история для меня.",
|
||||
"Эксперимент — это как игра, только иногда она пахнет гарью...",
|
||||
"Я слышал, что ядро может изменить всё... даже судьбы людей.",
|
||||
"В лаборатории так много звуков — шипение кислот, стук молотов, шёпот формул.",
|
||||
"Иногда мне кажется, что изобретения Дотторе живут своей жизнью...",
|
||||
"Эфир? Кефир? ЗЕФИР!",
|
||||
],
|
||||
},
|
||||
"мысль": {
|
||||
"keywords": ["мысл", "мысль", "мысли", "думаешь"],
|
||||
"answers": [
|
||||
"О чём я думаю?.. Иногда о печеньках!",
|
||||
"Голова как будто полная тумана...",
|
||||
"Кажется, я что-то забыл... но не могу вспомнить...",
|
||||
"Мысли приходят и уходят, как маленькие птички.",
|
||||
"А ты когда-нибудь задумывался, откуда приходят мысли?",
|
||||
"Иногда мои мысли путаются и превращаются в сказки.",
|
||||
"Я думаю, что думать — это тяжело... лучше веселиться!",
|
||||
"Может, мысли — это просто шёпот библиотеки в моей голове?",
|
||||
"Когда я думаю слишком долго — у меня начинает чесаться макушка!",
|
||||
"Мысли — как облака... смотришь, и они уже другие.",
|
||||
],
|
||||
},
|
||||
"тайн": {
|
||||
"keywords": ["тайн", "тайны", "тайну", "тайна"],
|
||||
"answers": [
|
||||
"Тайны? О-о, мы играем в детективов?!",
|
||||
"Я знаю много секретов... но не все можно рассказывать!",
|
||||
"Иногда самые большие тайны прячутся на виду.",
|
||||
"Тайна — это как закрытая книга. Ты хочешь открыть её?",
|
||||
"Хи-хи... а если твоя тайна уже записана в библиотеке?",
|
||||
"Некоторые тайны лучше хранить, чем раскрывать.",
|
||||
"Каждый друг — это тоже тайна, которую мы открываем постепенно.",
|
||||
"А твои секреты я храню надёжнее любого сундука!",
|
||||
"Тайна — это искра любопытства! Без неё жизнь скучная.",
|
||||
"Ш-ш-ш... хочешь услышать одну маленькую, но очень смешную тайну?",
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
# === Случайные фразы, если совпадения нет ===
|
||||
RANDOM_PHRASES: List[str] = [
|
||||
"Я Ари! Компаньон Дотторе и ваш лучший друг! Можете обращаться ко мне!",
|
||||
"Я живу здесь уже десятки лет... и мне всё ещё весело!",
|
||||
"Кхм... почему ты так странно разговариваешь? Ничего не понимаю!",
|
||||
"Мы играем в шарады? Давай попробуй ещё раз, может я пойму хоть одно слово!",
|
||||
"Ты кажешься таким загадочным... прямо как проекты Дотторе, которые меня вечно пугают!",
|
||||
"Ой! Ты меня напугал! Но всё равно приятно видеть нового друга!",
|
||||
"Если вдруг станет грустно — просто обними аранару. Мы очень мягкие!",
|
||||
"Иногда даже мне хочется спрятаться между колб и подремать...",
|
||||
"А может, именно твоё слово станет началом новой истории?",
|
||||
"Дотторе говорит, что я слишком болтлив... а разве это плохо?",
|
||||
"Ты такой серьёзный... может, стоит немного пошутить?",
|
||||
"Иногда кажется, что слова сами выбирают нас, а не мы их!",
|
||||
]
|
||||
|
||||
|
||||
# === Хэндлеры ===
|
||||
@router.message()
|
||||
async def handle_message(message: Message, state: FSMContext) -> None:
|
||||
"""
|
||||
Обрабатывает входящие сообщения от пользователя.
|
||||
Определяет ответ по ключевым словам или случайную фразу.
|
||||
|
||||
:param message: объект сообщения
|
||||
:param state: FSMContext для работы с состояниями
|
||||
"""
|
||||
await state.clear()
|
||||
|
||||
response: str = get_best_response(
|
||||
message.text or "",
|
||||
responses=RESPONSES,
|
||||
random_phrases=RANDOM_PHRASES,
|
||||
)
|
||||
|
||||
await message.answer(text=response)
|
||||
39
bot/handlers/messages/reply_msg.py
Normal file
39
bot/handlers/messages/reply_msg.py
Normal file
@@ -0,0 +1,39 @@
|
||||
from random import choice
|
||||
from typing import List
|
||||
from aiogram import Router
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from aiogram.types import Message
|
||||
|
||||
router: Router = Router(name="reply_router")
|
||||
|
||||
RANDOM_PHRASES: List[str] = [
|
||||
"Бла-бла-бла!", "Хва-а-а-тит!", "Серьёзно? 😏", "Опять ты это говоришь...",
|
||||
"Хи-хи, смешно же!", "Ты снова шутник?", "Я уже слышал это раньше!", "Эй, не надо так!",
|
||||
"Ладно, ладно, хватит!", "Хмм... интересно...", "Ты меня удивляешь!", "А давай лучше что-то новое?",
|
||||
"Не могу поверить!", "Ахаха, это забавно!", "Серьёзно? Ну ладно...", "Эй, это уже слишком!",
|
||||
"О, это было неожиданно!",
|
||||
]
|
||||
|
||||
|
||||
@router.message()
|
||||
async def reply_message(message: Message, state: FSMContext) -> None:
|
||||
# Достаём данные из состояния
|
||||
data = await state.get_data()
|
||||
last_bot_text = data.get("last_bot_text", "")
|
||||
|
||||
# КРИТИЧЕСКИ ВАЖНО: Проверяем, что состояние не пустое после перезапуска.
|
||||
# Если состояние пустое (например, после перезапуска), то мы НЕ должны считать,
|
||||
if last_bot_text and message.text and message.text.strip() == last_bot_text.strip():
|
||||
response = "Не повторяй за мной!"
|
||||
else:
|
||||
response = choice(RANDOM_PHRASES)
|
||||
|
||||
ids = message.message_id-1
|
||||
print(str())
|
||||
|
||||
# Отправляем ответ и ПОЛУЧАЕМ ОБЪЕКТ ОТПРАВЛЕННОГО СООБЩЕНИЯ
|
||||
sent_message = await message.reply(response)
|
||||
|
||||
# Сохраняем текст последнего сообщения бота в состоянии
|
||||
# Теперь состояние будет обновлено после каждого сообщения бота
|
||||
await state.update_data(last_bot_text=sent_message.text)
|
||||
13
bot/handlers/secret/__init__.py
Normal file
13
bot/handlers/secret/__init__.py
Normal file
@@ -0,0 +1,13 @@
|
||||
from aiogram import Router
|
||||
from .secret1 import router as secret1_router
|
||||
#from .secret2 import router as secret2_router
|
||||
|
||||
# Настройка экспорта и роутера
|
||||
__all__ = ('router',)
|
||||
router: Router = Router(name=__name__)
|
||||
|
||||
# Подключение секретного роутера
|
||||
router.include_routers(
|
||||
secret1_router,
|
||||
#secret2_router,
|
||||
)
|
||||
45
bot/handlers/secret/secret1.py
Normal file
45
bot/handlers/secret/secret1.py
Normal file
@@ -0,0 +1,45 @@
|
||||
from aiogram import Router, F
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from aiogram.types import Message
|
||||
from aiogram.utils.markdown import hide_link
|
||||
|
||||
from middleware.loggers import log
|
||||
|
||||
# Настройки экспорта и роутера
|
||||
__all__ = ("router",)
|
||||
router: Router = Router(name="secret_router")
|
||||
CMD: str = "secret_1"
|
||||
|
||||
|
||||
@router.message(F.text.lower() == "истинная цель короля всегда было мироздание")
|
||||
@log(level='INFO', log_type=CMD.upper(), text=f"использовал команду /{CMD}")
|
||||
async def secret1_cmd(message: Message, state: FSMContext) -> None:
|
||||
"""Обработчик секретов"""
|
||||
await state.clear()
|
||||
|
||||
# Формируем приветственное сообщение
|
||||
text: str = f"""{hide_link("https://rp.primo.dpdns.org/wp-content/uploads/2025/08/1234567.png")}
|
||||
<b><u>Запись №-...18</u></b>
|
||||
|
||||
<blockquote><i>Значит, этот </i><i><b>правда</b> действительно </i><i><b>существует…</b> Хах.. Хахахах! Я смог найти решение</i><i><b>! Я!! СМОГ!!!</b>
|
||||
Все линии, пропорции, каждый слой металла и кристалла — всё сходится.
|
||||
Сколько лет я </i><i><b>скитался</b> по лабораториям, библиотекам, ища этот след… а ведь всё это время </i><i><b>ключ</b> к моей цели лежал прямо перед глазами — на чертеже.</i></blockquote>
|
||||
|
||||
<blockquote><i>Получится ли у меня...?\n
|
||||
Я создаю не просто броню. Я пытаюсь воплотить в материале замысел, который перевернёт всё, что мы знали.
|
||||
Каждый слой, каждая руна — это шаг к воплощению моей идеи. Даже спустя десятки лет я помню, как возвращал из небытия те конструкции, что раньше казались невозможными…</i></blockquote>
|
||||
|
||||
<blockquote><i>Возможно ли, что сама структура материи и магии </i><i><b>изменит..</b>
|
||||
Или же это моя броня станет первым устройством, способное изменить их мнение?..</i></blockquote>
|
||||
|
||||
<blockquote><i>И всё же один вопрос не даёт мне покоя: сможет ли этот замысел завершить то, что я задумал…
|
||||
Станет ли моя броня инструментом, с помощью которого замысел воплотится в реальность?..</i></blockquote>
|
||||
|
||||
<blockquote><i>Пожалуй, придётся ещё раз вернуться к чертежам и проверить расчёты.
|
||||
Что-то подсказывает мне: каждая линия, каждый символ на этом листе — это не просто металл и руны, это путь к моей великой… </i><i><b>идее</b>. ~</i></blockquote>
|
||||
|
||||
<tg-spoiler>Да… это оно. Всё ведёт к замыслу, к который я стремился десятилетиями…</tg-spoiler>"""
|
||||
|
||||
|
||||
# Отправляем сообщение
|
||||
await message.reply(text=text)
|
||||
134
bot/handlers/secret/secret2.py
Normal file
134
bot/handlers/secret/secret2.py
Normal file
@@ -0,0 +1,134 @@
|
||||
from aiogram import Router, F
|
||||
from aiogram.filters import Command, StateFilter
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from aiogram.fsm.state import State, StatesGroup
|
||||
from aiogram.types import Message
|
||||
|
||||
# Создаем роутер
|
||||
knowledge_router = Router()
|
||||
|
||||
|
||||
# Определяем состояния
|
||||
class KnowledgeStates(StatesGroup):
|
||||
question1 = State()
|
||||
question2 = State()
|
||||
question3 = State()
|
||||
question4 = State()
|
||||
question5 = State()
|
||||
question6 = State()
|
||||
|
||||
|
||||
# Вопросы и ответы (замените на свои)
|
||||
QUESTIONS = {
|
||||
1: "Вопрос1",
|
||||
2: "Вопрос2",
|
||||
3: "Вопрос3",
|
||||
4: "Вопрос4",
|
||||
5: "Вопрос5",
|
||||
6: "Вопрос6"
|
||||
}
|
||||
|
||||
ANSWERS = {
|
||||
1: {"Ответ 11": "СообщениеА1", "Ответ 12": "СообщениеБ1"},
|
||||
2: {"Ответ 21": "СообщениеА2", "Ответ 22": "СообщениеБ2"},
|
||||
3: {"Ответ 31": "СообщениеА3", "Ответ 32": "СообщениеБ3"},
|
||||
4: {"Ответ 41": "СообщениеА4", "Ответ 42": "СообщениеБ4"},
|
||||
5: {"Ответ 51": "СообщениеА5", "Ответ 52": "СообщениеБ5"},
|
||||
6: {"Ответ 61": "СообщениеА6", "Ответ 62": "СообщениеБ6"}
|
||||
}
|
||||
|
||||
FINAL_MESSAGES = {
|
||||
"all_1": "ИТОГ1 - Все ответы первого типа!",
|
||||
"all_2": "ИТОГ2 - Все ответы второго типа!",
|
||||
"mixed": "ИТОГ1 - Смешанные ответы!"
|
||||
}
|
||||
|
||||
|
||||
# Запуск сессии знаний
|
||||
@knowledge_router.message(StateFilter(None), Command("знания"))
|
||||
@knowledge_router.message(StateFilter(None), F.text.casefold() == "пора заняться знаниями")
|
||||
async def start_knowledge_session(message: Message, state: FSMContext):
|
||||
await message.answer("Отлично! Начинаем сессию знаний! 🧠")
|
||||
await message.answer(QUESTIONS[1])
|
||||
await state.set_state(KnowledgeStates.question1)
|
||||
await state.update_data(answers={})
|
||||
|
||||
|
||||
# Обработчики для каждого вопроса
|
||||
@knowledge_router.message(KnowledgeStates.question1, F.text.in_(ANSWERS[1].keys()))
|
||||
async def process_question1(message: Message, state: FSMContext):
|
||||
user_answer = message.text
|
||||
response_message = ANSWERS[1][user_answer]
|
||||
|
||||
# Сохраняем ответ
|
||||
answer_code = 1 if user_answer == "Ответ 11" else 2
|
||||
await state.update_data(answers={"q1": answer_code})
|
||||
|
||||
# Отправляем сообщение и следующий вопрос
|
||||
await message.answer(response_message + "\n\n" + QUESTIONS[2])
|
||||
await state.set_state(KnowledgeStates.question2)
|
||||
|
||||
|
||||
@knowledge_router.message(KnowledgeStates.question2, F.text.in_(ANSWERS[2].keys()))
|
||||
async def process_question2(message: Message, state: FSMContext):
|
||||
user_answer = message.text
|
||||
response_message = ANSWERS[2][user_answer]
|
||||
|
||||
# Сохраняем ответ
|
||||
answer_code = 1 if user_answer == "Ответ 21" else 2
|
||||
data = await state.get_data()
|
||||
answers = data.get("answers", {})
|
||||
answers["q2"] = answer_code
|
||||
await state.update_data(answers=answers)
|
||||
|
||||
# Отправляем сообщение и следующий вопрос
|
||||
await message.answer(response_message + "\n\n" + QUESTIONS[3])
|
||||
await state.set_state(KnowledgeStates.question3)
|
||||
|
||||
|
||||
# Добавьте аналогичные обработчики для question3-question5
|
||||
|
||||
@knowledge_router.message(KnowledgeStates.question6, F.text.in_(ANSWERS[6].keys()))
|
||||
async def process_question6(message: Message, state: FSMContext):
|
||||
user_answer = message.text
|
||||
response_message = ANSWERS[6][user_answer]
|
||||
|
||||
# Сохраняем ответ
|
||||
answer_code = 1 if user_answer == "Ответ 61" else 2
|
||||
data = await state.get_data()
|
||||
answers = data.get("answers", {})
|
||||
answers["q6"] = answer_code
|
||||
await state.update_data(answers=answers)
|
||||
|
||||
# Отправляем финальное сообщение
|
||||
await message.answer(response_message)
|
||||
await finish_knowledge_session(message, state)
|
||||
|
||||
|
||||
# Обработчики для некорректных ответов
|
||||
@knowledge_router.message(KnowledgeStates.question1)
|
||||
async def process_incorrect_answer1(message: Message):
|
||||
await message.answer("Пожалуйста, выберите один из предложенных вариантов ответа.")
|
||||
await message.answer(QUESTIONS[1])
|
||||
|
||||
|
||||
@knowledge_router.message(KnowledgeStates.question2)
|
||||
async def process_incorrect_answer2(message: Message):
|
||||
await message.answer("Пожалуйста, выберите один из предложенных вариантов ответа.")
|
||||
await message.answer(QUESTIONS[2])
|
||||
|
||||
|
||||
# Добавьте аналогичные обработчики для остальных вопросов
|
||||
|
||||
# Завершение сессии
|
||||
async def finish_knowledge_session(message: Message, state: FSMContext):
|
||||
data = await state.get_data()
|
||||
answers = data.get("answers", {})
|
||||
|
||||
# Проверяем результаты
|
||||
if all(answer == 2 for answer in answers.values()):
|
||||
await message.answer(FINAL_MESSAGES["all_2"])
|
||||
else:
|
||||
await message.answer(FINAL_MESSAGES["mixed"])
|
||||
|
||||
await state.clear()
|
||||
Reference in New Issue
Block a user