195 lines
8.3 KiB
Python
195 lines
8.3 KiB
Python
from types import NoneType, UnionType
|
|
from aiogram.fsm.context import FSMContext
|
|
from aiogram.types import Message, CallbackQuery, InlineKeyboardButton
|
|
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
|
from babel.support import LazyProxy
|
|
from sqlmodel.ext.asyncio.session import AsyncSession
|
|
from typing import Any, get_args, get_origin
|
|
import ujson as json
|
|
|
|
from ..context import ContextData, CallbackCommand, CommandContext
|
|
from ....model.user import UserBase
|
|
from ....model.settings import Settings
|
|
from ....main import QBotApp
|
|
from ....model.bot_entity import BotEntity
|
|
from ....model.bot_enum import BotEnum
|
|
from ....model.descriptors import (EntityFieldDescriptor,
|
|
EntityDescriptor,
|
|
EntityCaptionCallable,
|
|
EntityItemCaptionCallable,
|
|
EntityFieldCaptionCallable)
|
|
|
|
|
|
def get_send_message(message: Message | CallbackQuery):
|
|
if isinstance(message, Message):
|
|
return message.answer
|
|
else:
|
|
return message.message.edit_text
|
|
|
|
|
|
def get_local_text(text: str, lang: str):
|
|
try:
|
|
text_obj = json.loads(text) #@IgnoreException
|
|
return text_obj.get(lang, text_obj[list(text_obj.keys())[0]])
|
|
except:
|
|
return text
|
|
|
|
|
|
def get_value_repr(value: Any, field_descriptor: EntityFieldDescriptor, locale: str | None = None) -> str:
|
|
type_ = field_descriptor.type_
|
|
origin = get_origin(type_)
|
|
if value is None:
|
|
return ""
|
|
|
|
if origin == UnionType:
|
|
args = get_args(type_)
|
|
if args[1] == NoneType:
|
|
type_ = args[0]
|
|
|
|
if isinstance(value, bool):
|
|
return "【✔︎】" if value else "【 】"
|
|
elif origin == list:
|
|
arg_type = None
|
|
args = get_args(type_)
|
|
if args:
|
|
arg_type = args[0]
|
|
if arg_type and issubclass(arg_type, BotEntity):
|
|
if locale and arg_type.bot_entity_descriptor.fields_descriptors["name"].localizable:
|
|
return "[" + ", ".join([get_local_text(value = item.name, locale = locale) for item in value]) + "]"
|
|
else:
|
|
return "[" + ", ".join([str(item.name) for item in value]) + "]"
|
|
elif arg_type and issubclass(arg_type, BotEnum):
|
|
return "[" + ", ".join(item.localized(locale) for item in value) + "]"
|
|
elif arg_type == str:
|
|
return "[" + ", ".join([f"\"{item}\"" for item in value]) + "]"
|
|
else:
|
|
return "[" + ", ".join([str(item) for item in value]) + "]"
|
|
elif issubclass(type_, BotEntity):
|
|
if type_.bot_entity_descriptor.fields_descriptors["name"].localizable:
|
|
return get_local_text(value = value.name, locale = locale)
|
|
return value.name
|
|
elif issubclass(type_, BotEnum):
|
|
return value.localized(locale)
|
|
elif isinstance(value, str):
|
|
if field_descriptor and field_descriptor.localizable:
|
|
return get_local_text(value, locale)
|
|
return value
|
|
elif isinstance(value, int):
|
|
return str(value)
|
|
elif isinstance(value, float):
|
|
return str(value)
|
|
else:
|
|
return str(value)
|
|
|
|
|
|
def get_callable_str(callable_str: str | LazyProxy | EntityCaptionCallable | EntityItemCaptionCallable | EntityFieldCaptionCallable,
|
|
descriptor: EntityFieldDescriptor | EntityDescriptor,
|
|
entity: Any = None,
|
|
value: Any = None) -> str:
|
|
|
|
if isinstance(callable_str, str):
|
|
return callable_str
|
|
elif isinstance(callable_str, LazyProxy):
|
|
return callable_str.value
|
|
elif callable(callable_str):
|
|
return callable_str(*(descriptor, entity, value))
|
|
|
|
|
|
async def authorize_command(user: UserBase,
|
|
callback_data: ContextData):
|
|
|
|
if (callback_data.command == CallbackCommand.MENU_ENTRY_PARAMETERS or
|
|
callback_data.context == CommandContext.SETTING_EDIT):
|
|
allowed_roles = (await Settings.get(Settings.SECURITY_SETTINGS_ROLES))
|
|
return any(role in user.roles for role in allowed_roles)
|
|
|
|
return False
|
|
|
|
|
|
def get_entity_descriptor(app: QBotApp, callback_data: ContextData) -> EntityDescriptor | None:
|
|
|
|
if callback_data.entity_name:
|
|
return app.entity_metadata.entity_descriptors[callback_data.entity_name]
|
|
return None
|
|
|
|
|
|
def get_field_descriptor(app: QBotApp, callback_data: ContextData) -> EntityFieldDescriptor | None:
|
|
|
|
if callback_data.context == CommandContext.SETTING_EDIT:
|
|
return Settings.list_params()[callback_data.field_name]
|
|
elif callback_data.context in [CommandContext.ENTITY_CREATE, CommandContext.ENTITY_EDIT]:
|
|
entity_descriptor = get_entity_descriptor(app, callback_data)
|
|
if entity_descriptor:
|
|
return entity_descriptor.fields_descriptors.get(callback_data.field_name)
|
|
return None
|
|
|
|
|
|
def add_pagination_controls(keyboard_builder: InlineKeyboardBuilder,
|
|
callback_data: ContextData,
|
|
total_pages: int,
|
|
command: CallbackCommand,
|
|
page: int):
|
|
|
|
if total_pages > 1:
|
|
navigation_buttons = []
|
|
ContextData(**callback_data.model_dump()).__setattr__
|
|
if total_pages > 10:
|
|
navigation_buttons.append(InlineKeyboardButton(text = "⏮️",
|
|
callback_data = ContextData(
|
|
command = command,
|
|
context = callback_data.context,
|
|
entity_name = callback_data.entity_name,
|
|
entity_id = callback_data.entity_id,
|
|
field_name = callback_data.field_name,
|
|
data = "1" if page != 1 else "skip",
|
|
save_state = True).pack()))
|
|
navigation_buttons.append(InlineKeyboardButton(text = "⏪️",
|
|
callback_data = ContextData(
|
|
command = command,
|
|
context = callback_data.context,
|
|
entity_name = callback_data.entity_name,
|
|
entity_id = callback_data.entity_id,
|
|
field_name = callback_data.field_name,
|
|
data = str(max(page - 10, 1)) if page > 1 else "skip",
|
|
save_state = True).pack()))
|
|
|
|
navigation_buttons.append(InlineKeyboardButton(text = f"◀️",
|
|
callback_data = ContextData(
|
|
command = command,
|
|
context = callback_data.context,
|
|
entity_name = callback_data.entity_name,
|
|
entity_id = callback_data.entity_id,
|
|
field_name = callback_data.field_name,
|
|
data = str(max(page - 1, 1)) if page > 1 else "skip",
|
|
save_state = True).pack()))
|
|
navigation_buttons.append(InlineKeyboardButton(text = f"▶️",
|
|
callback_data = ContextData(
|
|
command = command,
|
|
context = callback_data.context,
|
|
entity_name = callback_data.entity_name,
|
|
entity_id = callback_data.entity_id,
|
|
field_name = callback_data.field_name,
|
|
data = str(min(page + 1, total_pages)) if page < total_pages else "skip",
|
|
save_state = True).pack()))
|
|
|
|
if total_pages > 10:
|
|
navigation_buttons.append(InlineKeyboardButton(text = "⏩️",
|
|
callback_data = ContextData(
|
|
command = command,
|
|
context = callback_data.context,
|
|
entity_name = callback_data.entity_name,
|
|
entity_id = callback_data.entity_id,
|
|
field_name = callback_data.field_name,
|
|
data = str(min(page + 10, total_pages)) if page < total_pages else "skip",
|
|
save_state = True).pack()))
|
|
navigation_buttons.append(InlineKeyboardButton(text = "⏭️",
|
|
callback_data = ContextData(
|
|
command = command,
|
|
context = callback_data.context,
|
|
entity_name = callback_data.entity_name,
|
|
entity_id = callback_data.entity_id,
|
|
field_name = callback_data.field_name,
|
|
data = str(total_pages) if page != total_pages else "skip",
|
|
save_state = True).pack()))
|
|
|
|
keyboard_builder.row(*navigation_buttons) |