mirror of
https://github.com/koloideal/Quizzi.git
synced 2026-06-10 02:15:29 +03:00
update
This commit is contained in:
+15
-2
@@ -24,10 +24,23 @@
|
||||
• Или отправьте команду /start
|
||||
|
||||
ШАГ 2: Вход в админ-панель
|
||||
|
||||
СПОСОБ 1: Получение прав администратора через пароль
|
||||
• Отправьте команду /admin_login
|
||||
• Введите пароль администратора (получите у создателя бота)
|
||||
• При правильном пароле вы получите права администратора
|
||||
• Создатель бота получит уведомление о новом администраторе
|
||||
• После этого используйте команду /admin для входа в панель
|
||||
|
||||
СПОСОБ 2: Прямой вход (если уже администратор)
|
||||
• Отправьте команду /admin
|
||||
• Если вы администратор, откроется админ-панель
|
||||
• Если команда не работает - обратитесь к создателю бота (@kolo_id)
|
||||
• Только создатель бота имеет права назначать администраторов
|
||||
• Если команда не работает - используйте /admin_login
|
||||
|
||||
⚠️ ВАЖНО:
|
||||
• Лимит попыток ввода пароля: 5 попыток в час
|
||||
• При превышении лимита нужно подождать
|
||||
• Только создатель бота имеет права назначать администраторов напрямую
|
||||
|
||||
═══════════════════════════════════════════════════════════════════════════════
|
||||
2. ГЛАВНОЕ МЕНЮ АДМИНКИ
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
[bot]
|
||||
token = "1234567890"
|
||||
creator_id = 1234567890
|
||||
admin_password = "your_admin_password"
|
||||
|
||||
[security]
|
||||
encode_key = "encode_key"
|
||||
|
||||
@@ -25,6 +25,7 @@ from quizzi.application.bot.user_dialogs.deeplink import deeplink_dialog
|
||||
from quizzi.application.bot.user_dialogs.main_menu import user_menu_dialog
|
||||
from quizzi.application.bot.user_dialogs.registration import registration_dialog
|
||||
from quizzi.application.bot.user_dialogs.take_test import take_test_dialog
|
||||
from quizzi.application.bot.user_dialogs.admin_login import admin_login_dialog
|
||||
from quizzi.infrastructure.database.repo.test import TestRepository
|
||||
from quizzi.infrastructure.database.repo.user import UserRepository
|
||||
from quizzi.infrastructure.di import DatabaseProvider, SchedulerProvider, ServiceProvider
|
||||
@@ -62,6 +63,7 @@ async def main() -> None:
|
||||
take_test_dialog,
|
||||
registration_dialog,
|
||||
deeplink_dialog,
|
||||
admin_login_dialog,
|
||||
shared_tests_dialog,
|
||||
shared_groups_dialog,
|
||||
shared_broadcast_dialog,
|
||||
|
||||
@@ -9,7 +9,7 @@ from dishka.integrations.aiogram import FromDishka
|
||||
|
||||
from quizzi.application.bot.admin_dialogs.states import AdminMenuSG
|
||||
from quizzi.application.bot.creator_dialogs.states import CreatorMenuSG
|
||||
from quizzi.application.bot.user_dialogs.states import UserDeeplinkSG, UserMenuSG, UserRegistrationSG
|
||||
from quizzi.application.bot.user_dialogs.states import UserAdminLoginSG, UserDeeplinkSG, UserMenuSG, UserRegistrationSG
|
||||
from quizzi.service.test import TestService
|
||||
from quizzi.service.user import UserService
|
||||
|
||||
@@ -165,6 +165,13 @@ async def creator_command(_message: Message, dialog_manager: DialogManager) -> N
|
||||
await dialog_manager.start(CreatorMenuSG.main, mode=StartMode.RESET_STACK)
|
||||
|
||||
|
||||
@router.message(Command("admin_login"))
|
||||
async def admin_login_command(_message: Message, dialog_manager: DialogManager) -> None:
|
||||
assert _message.from_user is not None
|
||||
logger.info("Admin login attempt: user_id=%d", _message.from_user.id)
|
||||
await dialog_manager.start(UserAdminLoginSG.password_input, mode=StartMode.RESET_STACK)
|
||||
|
||||
|
||||
@router.error()
|
||||
async def dialog_error_handler(event: ErrorEvent, dialog_manager: DialogManager) -> None:
|
||||
if isinstance(event.exception, (UnknownIntent, OutdatedIntent)):
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
from aiogram.types import Message
|
||||
from aiogram_dialog import Dialog, DialogManager, Window
|
||||
from aiogram_dialog.widgets.input import MessageInput
|
||||
from aiogram_dialog.widgets.kbd import Button
|
||||
from aiogram_dialog.widgets.text import Const
|
||||
from dishka import FromDishka
|
||||
from dishka.integrations.aiogram_dialog import inject
|
||||
|
||||
from quizzi.application.bot.user_dialogs.states import UserAdminLoginSG
|
||||
from quizzi.infrastructure.database.dao.user import UserDAO
|
||||
from quizzi.infrastructure.utils.config import Config
|
||||
from quizzi.infrastructure.utils.rate_limiter import PasswordRateLimiter
|
||||
|
||||
|
||||
password_limiter = PasswordRateLimiter()
|
||||
|
||||
|
||||
@inject
|
||||
async def on_password_input(
|
||||
message: Message,
|
||||
_widget: MessageInput,
|
||||
manager: DialogManager,
|
||||
user_dao: FromDishka[UserDAO],
|
||||
config: FromDishka[Config],
|
||||
):
|
||||
assert message.from_user is not None
|
||||
assert message.text is not None
|
||||
|
||||
user_id = message.from_user.id
|
||||
|
||||
allowed, wait_time = await password_limiter.check(user_id)
|
||||
|
||||
if not allowed:
|
||||
minutes = int(wait_time // 60)
|
||||
seconds = int(wait_time % 60)
|
||||
await message.answer(
|
||||
f"❌ Слишком много попыток. Попробуйте через {minutes} мин {seconds} сек"
|
||||
)
|
||||
return
|
||||
|
||||
password = message.text.strip()
|
||||
|
||||
if password == config.bot.admin_password:
|
||||
await user_dao.update(user_id, is_admin=True)
|
||||
await message.answer("✅ Вы успешно получили права администратора")
|
||||
|
||||
try:
|
||||
await message.bot.send_message(
|
||||
config.bot.creator_id,
|
||||
f"🔔 Новый администратор:\n"
|
||||
f"ID: {user_id}\n"
|
||||
f"Username: @{message.from_user.username or 'нет'}\n"
|
||||
f"Имя: {message.from_user.first_name}"
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
await manager.done()
|
||||
else:
|
||||
await message.answer("❌ Неверный пароль")
|
||||
|
||||
|
||||
async def on_cancel(_callback, _button, manager: DialogManager):
|
||||
await manager.done()
|
||||
|
||||
|
||||
admin_login_dialog = Dialog(
|
||||
Window(
|
||||
Const("<b>🔐 Вход в панель администратора</b>\n\n🔑 Введите пароль администратора:"),
|
||||
MessageInput(on_password_input),
|
||||
Button(Const("❌ Отмена"), id="cancel", on_click=on_cancel),
|
||||
state=UserAdminLoginSG.password_input,
|
||||
),
|
||||
)
|
||||
@@ -30,3 +30,7 @@ class UserDeeplinkSG(StatesGroup):
|
||||
class UserRegistrationSG(StatesGroup):
|
||||
input_name = State()
|
||||
select_group = State()
|
||||
|
||||
|
||||
class UserAdminLoginSG(StatesGroup):
|
||||
password_input = State()
|
||||
|
||||
@@ -8,6 +8,7 @@ from typing import Self
|
||||
class BotConfig:
|
||||
token: str
|
||||
creator_id: int
|
||||
admin_password: str
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -47,7 +48,8 @@ class Config:
|
||||
return cls(
|
||||
bot=BotConfig(
|
||||
token=str(bot_data["token"]),
|
||||
creator_id=int(bot_data["creator_id"])
|
||||
creator_id=int(bot_data["creator_id"]),
|
||||
admin_password=str(bot_data["admin_password"])
|
||||
),
|
||||
database=DatabaseConfig(
|
||||
host=str(db_data["host"]),
|
||||
|
||||
Reference in New Issue
Block a user