Initial commit

This commit is contained in:
Lolzteam
2026-07-30 10:22:59 +00:00
commit 8953b2f4bc
48 changed files with 2564 additions and 0 deletions
+33
View File
@@ -0,0 +1,33 @@
# - *- coding: utf- 8 - *-
from aiogram import Dispatcher
from tgbot.routers import main_errors, main_missed, main_start
from tgbot.routers.admin import admin_menu
from tgbot.routers.user import user_menu
from tgbot.utils.misc.bot_filters import IsAdmin, IsPrivate
# Подключение всех роутеров
def register_all_routers(dp: Dispatcher):
# Общие фильтры для приватных чатов
main_errors.router.message.filter(IsPrivate())
main_start.router.message.filter(IsPrivate())
user_menu.router.message.filter(IsPrivate())
user_menu.router.callback_query.filter(IsPrivate())
admin_menu.router.message.filter(IsPrivate(), IsAdmin())
admin_menu.router.callback_query.filter(IsPrivate(), IsAdmin())
main_missed.router.message.filter(IsPrivate())
main_missed.router.callback_query.filter(IsPrivate())
# Базовые роутеры, которые нужны всегда
dp.include_router(main_errors.router) # Ошибки
dp.include_router(main_start.router) # Старт и главное меню
# Роутеры для пользователей и админов
dp.include_router(user_menu.router) # Пользовательские обработчики
dp.include_router(admin_menu.router) # Админские обработчики
# Обработка всего, что не поймали выше
dp.include_router(main_missed.router) # Пропущенные сообщения и колбэки
View File
+111
View File
@@ -0,0 +1,111 @@
# - *- coding: utf- 8 - *-
from pathlib import Path
import aiofiles
from aiogram import Router, Bot, F
from aiogram.filters import Command
from aiogram.types import FSInputFile, Message, CallbackQuery
from aiogram.utils.media_group import MediaGroupBuilder
from tgbot.data.config import BOT_DATABASE_EXPORT, PATH_DATABASE, PATH_LOGS
from tgbot.database.db_users import UserModel
from tgbot.keyboards.inline_main import admin_finl
from tgbot.utils.const_functions import get_date
from tgbot.utils.misc.bot_models import FSM, ARS
router = Router(name=__name__)
LOGS_DIR = Path(PATH_LOGS).parent
SERVICE_LOG_FILES = (
LOGS_DIR / "sv_log_err.log",
LOGS_DIR / "sv_log_out.log",
)
# Кнопка админского меню
@router.message(F.text == 'Админ-меню')
async def admin_button_inline(message: Message, bot: Bot, state: FSM, arSession: ARS, User: UserModel):
await state.clear()
await message.answer(
"Инлайн-клавиатура админа",
reply_markup=admin_finl()
)
# Колбэк для демо-действия админа
@router.callback_query(F.data == 'admin_inline_x')
async def admin_callback_inline_x(call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS, User: UserModel):
await call.answer("Админское действие выполнено")
# Колбэк с параметром из админской кнопки
@router.callback_query(F.data.startswith('admin_inline:'))
async def admin_callback_inline(call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS, User: UserModel):
get_data = call.data.split(":")[1]
await call.answer(f"Выбран админский раздел: {get_data}", True)
# Отправка файла базы админам
@router.message(Command(commands=['db', 'database']))
async def admin_database(message: Message, bot: Bot, state: FSM, arSession: ARS, User: UserModel):
await state.clear()
if not BOT_DATABASE_EXPORT:
await message.answer("<b>📦 Экспорт базы данных отключён в настройках</b>")
return
if not Path(PATH_DATABASE).is_file():
await message.answer("<b>📦 Файл базы данных не найден</b>")
return
await message.answer_document(
FSInputFile(PATH_DATABASE),
caption=f"<b>📦 #БЭКАП | <code>{get_date()}</code></b>",
)
# Отправка логов админам
@router.message(Command(commands=['log', 'logs']))
async def admin_log(message: Message, bot: Bot, state: FSM, arSession: ARS, User: UserModel):
await state.clear()
log_files = []
if Path(PATH_LOGS).is_file():
log_files.append(PATH_LOGS)
for log_file in SERVICE_LOG_FILES:
if log_file.is_file():
log_files.append(str(log_file))
caption = f"<b>🖨 #ЛОГИ | <code>{get_date(full=False)}</code></b>"
if len(log_files) == 0:
await message.answer("<b>🖨 Логи не найдены</b>")
elif len(log_files) == 1:
await message.answer_document(FSInputFile(log_files[0]), caption=caption)
else:
media_group = MediaGroupBuilder(caption=caption)
for log_file in log_files:
media_group.add_document(media=FSInputFile(log_file))
await message.answer_media_group(media=media_group.build())
# Очистка файлов логов
@router.message(Command(commands=['clear_log', 'clear_logs', 'log_clear', 'logs_clear']))
async def admin_logs_clear(message: Message, bot: Bot, state: FSM, arSession: ARS, User: UserModel):
await state.clear()
log_files = [Path(PATH_LOGS), *SERVICE_LOG_FILES]
for log_file in log_files:
if not log_file.is_file():
continue
async with aiofiles.open(log_file, "w", encoding="utf-8") as file:
await file.write(f"{get_date()} | ЛОГИ ОЧИЩЕНЫ")
await message.answer("<b>🖨 Логи очищены</b>")
+27
View File
@@ -0,0 +1,27 @@
# - *- coding: utf- 8 - *-
from aiogram import Router
from aiogram.exceptions import TelegramBadRequest
from aiogram.filters import ExceptionTypeFilter
from aiogram.handlers import ErrorHandler
from tgbot.utils.misc.bot_logging import bot_logger
router = Router(name=__name__)
# Ошибка при отправке сообщения пользователю, который заблокировал бота
# @router.errors(ExceptionTypeFilter(TelegramForbiddenError))
# class ForbiddenErrorHandler(ErrorHandler):
# async def handle(self):
# ...
# Безопасно игнорируем повторное редактирование сообщения без изменений
@router.errors(ExceptionTypeFilter(TelegramBadRequest))
class MessageNotModifiedHandler(ErrorHandler):
async def handle(self):
if "message is not modified" in self.exception_message.lower():
bot_logger.debug("Telegram отклонил повторное редактирование сообщения без изменений")
return True
raise self.event
+36
View File
@@ -0,0 +1,36 @@
# - *- coding: utf- 8 - *-
from aiogram import Router, Bot, F
from aiogram.types import CallbackQuery, Message
from tgbot.database import ModelUsers
from tgbot.utils.const_functions import del_message
from tgbot.utils.misc.bot_models import FSM, ARS
router = Router(name=__name__)
# Колбэк для удаления текущего сообщения
@router.callback_query(F.data == 'close_this')
async def main_callback_close(call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS, User: ModelUsers):
await del_message(call.message)
# Колбэк-заглушка для пустых кнопок
@router.callback_query(F.data == '...')
async def main_callback_answer(call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS, User: ModelUsers):
await call.answer(cache_time=30)
# Ответ на колбэк, который никто не обработал
@router.callback_query()
async def main_callback_missed(call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS, User: ModelUsers):
await call.answer(f"❗️ Неизвестный колбэк: {call.data}", True)
# Ответ на неизвестные сообщения
@router.message()
async def main_message_missed(message: Message, bot: Bot, state: FSM, arSession: ARS, User: ModelUsers):
await message.answer(
"♦️ Неизвестная команда\n"
"♦️ Введите /start",
)
+26
View File
@@ -0,0 +1,26 @@
# - *- coding: utf- 8 - *-
from aiogram import Router, Bot, F
from aiogram.filters import Command
from aiogram.types import Message
from tgbot.database.db_users import UserModel
from tgbot.keyboards.reply_main import menu_frep
from tgbot.utils.const_functions import ded
from tgbot.utils.misc.bot_models import FSM, ARS
router = Router(name=__name__)
# Главное меню пользователя
@router.message(F.text.in_(('menu', 'return', 'start')))
@router.message(Command(commands=['start']))
async def main_start(message: Message, bot: Bot, state: FSM, arSession: ARS, User: UserModel):
await state.clear()
await message.answer(
ded(f"""
🔸 Привет, {User.user_name}
🔸 Введи /start или /menu
"""),
reply_markup=menu_frep(message.from_user.id),
)
View File
+47
View File
@@ -0,0 +1,47 @@
# - *- coding: utf- 8 - *-
from aiogram import Router, Bot, F
from aiogram.filters import Command
from aiogram.types import Message, CallbackQuery
from tgbot.database.db_users import UserModel
from tgbot.keyboards.inline_main import user_finl
from tgbot.keyboards.reply_main import menu_frep
from tgbot.utils.misc.bot_models import FSM, ARS
router = Router(name=__name__)
# Кнопка пользовательского меню
@router.message(F.text == 'Пользовательское меню')
async def user_button_inline(message: Message, bot: Bot, state: FSM, arSession: ARS, User: UserModel):
await state.clear()
await message.answer(
"Инлайн-клавиатура пользователя",
reply_markup=user_finl()
)
# Команда возврата в меню
@router.message(Command(commands="menu"))
async def user_command_menu(message: Message, bot: Bot, state: FSM, arSession: ARS, User: UserModel):
await state.clear()
await message.answer(
"Команда /menu открывает главное меню",
reply_markup=menu_frep(message.from_user.id),
)
# Колбэк для демо-действия
@router.callback_query(F.data == 'user_inline_x')
async def user_callback_inline_x(call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS, User: UserModel):
await call.answer("Действие выполнено")
# Колбэк с параметром из пользовательской кнопки
@router.callback_query(F.data.startswith('user_inline:'))
async def user_callback_inline(call: CallbackQuery, bot: Bot, state: FSM, arSession: ARS, User: UserModel):
get_data = call.data.split(":")[1]
await call.answer(f"Выбран раздел: {get_data}", True)