This commit is contained in:
2026-03-01 15:58:47 +03:00
parent 1110d89bb0
commit cf0b0309fc
12 changed files with 430 additions and 95 deletions
@@ -0,0 +1,374 @@
from aiogram.types import CallbackQuery
from aiogram_dialog import Window, DialogManager
from aiogram_dialog.widgets.text import Format, Const
from aiogram_dialog.widgets.kbd import SwitchTo, Button, Select, ScrollingGroup, Row
from dishka import FromDishka
from dishka.integrations.aiogram_dialog import inject
from dutylog.application.bot.user_dialogs.states import CreatorMenuSG, AdminMenuSG
from dutylog.infrastructure.database.repositories.users_repository import UsersRepository
@inject
async def get_admins_list_data(
users_repository: FromDishka[UsersRepository],
**kwargs,
) -> dict[str, str | list[tuple[str, int]]]:
all_users = await users_repository.get_all_users()
admins = [u for u in all_users if u.is_admin]
if not admins:
content = """
<blockquote>👨‍💼 <b>Администраторы</b></blockquote>
⚠️ Нет администраторов в системе.
"""
admins_list = []
else:
content = f"""
<blockquote>👨‍💼 <b>Администраторы</b></blockquote>
Всего администраторов: <code>{len(admins)}</code>
Выберите администратора для просмотра информации:
"""
admins_list = []
for admin in admins:
display_name = f"@{admin.username}" if admin.username else f"ID: {admin.id}"
if admin.first_name:
display_name = f"{admin.first_name} ({display_name})"
admins_list.append((display_name, admin.id))
return {
"content": content,
"admins": admins_list,
}
async def on_admin_selected(
callback: CallbackQuery,
widget,
dialog_manager: DialogManager,
item_id: str,
) -> None:
dialog_manager.dialog_data["selected_admin_id"] = int(item_id)
await dialog_manager.switch_to(CreatorMenuSG.admin_info)
async def on_add_admin_click(
callback: CallbackQuery,
button: Button,
dialog_manager: DialogManager,
) -> None:
await dialog_manager.switch_to(CreatorMenuSG.add_admin_select_user)
@inject
async def get_admin_info_data(
users_repository: FromDishka[UsersRepository],
dialog_manager: DialogManager,
**kwargs,
) -> dict[str, str]:
admin_id = dialog_manager.dialog_data.get("selected_admin_id")
if not admin_id:
return {"content": "⚠️ Администратор не выбран"}
admin = await users_repository.get_user_by_id(int(admin_id))
if not admin:
return {"content": "⚠️ Администратор не найден"}
username = f"@{admin.username}" if admin.username else ""
first_name = admin.first_name or ""
last_name = admin.last_name or ""
content = f"""
<blockquote>👨‍💼 <b>Информация об администраторе</b></blockquote>
<b>ID:</b> <code>{admin.id}</code>
<b>Username:</b> {username}
<b>Имя:</b> <code>{first_name}</code>
<b>Фамилия:</b> <code>{last_name}</code>
<b>Дата добавления:</b> <code>{admin.created_at.strftime('%d.%m.%Y %H:%M')}</code>
"""
return {"content": content}
async def on_remove_admin_click(
callback: CallbackQuery,
button: Button,
dialog_manager: DialogManager,
) -> None:
await dialog_manager.switch_to(CreatorMenuSG.remove_admin_confirm)
@inject
async def get_remove_admin_confirm_data(
users_repository: FromDishka[UsersRepository],
dialog_manager: DialogManager,
**kwargs,
) -> dict[str, str]:
admin_id = dialog_manager.dialog_data.get("selected_admin_id")
if not admin_id:
return {"content": "⚠️ Администратор не выбран"}
admin = await users_repository.get_user_by_id(int(admin_id))
if not admin:
return {"content": "⚠️ Администратор не найден"}
username = f"@{admin.username}" if admin.username else f"ID: {admin.id}"
display_name = admin.first_name or username
content = f"""
<blockquote>⚠️ <b>Подтверждение удаления</b></blockquote>
Вы уверены, что хотите удалить администратора <b>{display_name}</b>?
Пользователь потеряет права администратора.
"""
return {"content": content}
@inject
async def on_remove_admin_confirm(
callback: CallbackQuery,
button: Button,
dialog_manager: DialogManager,
users_repository: FromDishka[UsersRepository],
) -> None:
admin_id = dialog_manager.dialog_data.get("selected_admin_id")
if not admin_id:
await callback.answer("⚠️ Администратор не выбран", show_alert=True)
return
await users_repository.update_user(int(admin_id), is_admin=False)
await callback.answer("✅ Администратор удалён!")
await dialog_manager.switch_to(CreatorMenuSG.admins_list)
async def on_remove_admin_cancel(
callback: CallbackQuery,
button: Button,
dialog_manager: DialogManager,
) -> None:
await dialog_manager.switch_to(CreatorMenuSG.admin_info)
@inject
async def get_add_admin_select_user_data(
users_repository: FromDishka[UsersRepository],
**kwargs,
) -> dict[str, str | list[tuple[str, int]]]:
all_users = await users_repository.get_all_users()
non_admin_users = [u for u in all_users if not u.is_admin]
if not non_admin_users:
content = """
<blockquote> <b>Добавить администратора</b></blockquote>
⚠️ Нет пользователей, которых можно сделать администраторами.
Все пользователи уже являются администраторами.
"""
users_list = []
else:
content = f"""
<blockquote> <b>Добавить администратора</b></blockquote>
Всего пользователей: <code>{len(non_admin_users)}</code>
Выберите пользователя для назначения администратором:
"""
users_list = []
for user in non_admin_users:
display_name = f"@{user.username}" if user.username else f"ID: {user.id}"
if user.first_name:
display_name = f"{user.first_name} ({display_name})"
users_list.append((display_name, user.id))
return {
"content": content,
"users": users_list,
}
async def on_user_selected(
callback: CallbackQuery,
widget,
dialog_manager: DialogManager,
item_id: str,
) -> None:
dialog_manager.dialog_data["selected_user_id"] = int(item_id)
await dialog_manager.switch_to(CreatorMenuSG.add_admin_confirm)
@inject
async def get_add_admin_confirm_data(
users_repository: FromDishka[UsersRepository],
dialog_manager: DialogManager,
**kwargs,
) -> dict[str, str]:
user_id = dialog_manager.dialog_data.get("selected_user_id")
if not user_id:
return {"content": "⚠️ Пользователь не выбран"}
user = await users_repository.get_user_by_id(int(user_id))
if not user:
return {"content": "⚠️ Пользователь не найден"}
username = f"@{user.username}" if user.username else f"ID: {user.id}"
display_name = user.first_name or username
content = f"""
<blockquote>⚠️ <b>Подтверждение</b></blockquote>
Вы уверены, что хотите назначить <b>{display_name}</b> администратором?
Пользователь получит доступ к панели управления.
"""
return {"content": content}
@inject
async def on_add_admin_confirm(
callback: CallbackQuery,
button: Button,
dialog_manager: DialogManager,
users_repository: FromDishka[UsersRepository],
) -> None:
user_id = dialog_manager.dialog_data.get("selected_user_id")
if not user_id:
await callback.answer("⚠️ Пользователь не выбран", show_alert=True)
return
await users_repository.update_user(int(user_id), is_admin=True)
await callback.answer("✅ Администратор добавлен!")
await dialog_manager.switch_to(CreatorMenuSG.admins_list)
async def on_add_admin_cancel(
callback: CallbackQuery,
button: Button,
dialog_manager: DialogManager,
) -> None:
await dialog_manager.switch_to(CreatorMenuSG.add_admin_select_user)
async def on_back_to_main(
callback: CallbackQuery,
button: Button,
dialog_manager: DialogManager,
) -> None:
await dialog_manager.done()
admins_list_window = Window(
Format("{content}"),
ScrollingGroup(
Select(
Format("{item[0]}"),
id="admin_select",
item_id_getter=lambda x: x[1],
items="admins",
on_click=on_admin_selected,
),
id="admins_scroll",
width=1,
height=8,
),
Button(
Const("➕ Добавить администратора"),
id="add_admin_btn",
on_click=on_add_admin_click,
),
Button(
Const("◀️ Назад"),
id="back_to_main_from_admins",
on_click=on_back_to_main,
),
state=CreatorMenuSG.admins_list,
getter=get_admins_list_data,
)
admin_info_window = Window(
Format("{content}"),
Button(
Const("🗑 Удалить администратора"),
id="remove_admin_btn",
on_click=on_remove_admin_click,
),
SwitchTo(
Const("◀️ Назад"),
id="back_to_admins_list",
state=CreatorMenuSG.admins_list,
),
state=CreatorMenuSG.admin_info,
getter=get_admin_info_data,
)
remove_admin_confirm_window = Window(
Format("{content}"),
Row(
Button(
Const("✅ Да"),
id="confirm_remove_admin",
on_click=on_remove_admin_confirm,
),
Button(
Const("❌ Нет"),
id="cancel_remove_admin",
on_click=on_remove_admin_cancel,
),
),
state=CreatorMenuSG.remove_admin_confirm,
getter=get_remove_admin_confirm_data,
)
add_admin_select_user_window = Window(
Format("{content}"),
ScrollingGroup(
Select(
Format("{item[0]}"),
id="user_select",
item_id_getter=lambda x: x[1],
items="users",
on_click=on_user_selected,
),
id="users_scroll",
width=1,
height=8,
),
SwitchTo(
Const("◀️ Назад"),
id="back_to_admins_from_add",
state=CreatorMenuSG.admins_list,
),
state=CreatorMenuSG.add_admin_select_user,
getter=get_add_admin_select_user_data,
)
add_admin_confirm_window = Window(
Format("{content}"),
Row(
Button(
Const("✅ Да"),
id="confirm_add_admin",
on_click=on_add_admin_confirm,
),
Button(
Const("❌ Нет"),
id="cancel_add_admin",
on_click=on_add_admin_cancel,
),
),
state=CreatorMenuSG.add_admin_confirm,
getter=get_add_admin_confirm_data,
)