feat: entity events
All checks were successful
Build Docs / changes (push) Successful in 20s
Build Docs / build-docs (push) Has been skipped
Build Docs / deploy-docs (push) Has been skipped

This commit is contained in:
Alexander Kalinovsky
2025-03-10 22:10:09 +07:00
parent dd56d3f312
commit 02aec23b84
5 changed files with 39 additions and 4 deletions

View File

@@ -15,6 +15,7 @@ from .model.descriptors import (
Filter as Filter,
EntityPermission as EntityPermission,
CommandCallbackContext as CommandCallbackContext,
EntityEventContext as EntityEventContext,
CommandButton as CommandButton,
FieldEditButton as FieldEditButton,
InlineButton as InlineButton,

View File

@@ -1,3 +1,4 @@
from inspect import iscoroutinefunction
from aiogram import Router, F
from aiogram.types import Message, CallbackQuery
from aiogram.fsm.context import FSMContext
@@ -12,7 +13,7 @@ from ..user_handlers.main import cammand_handler
from ....model import EntityPermission
from ....model.user import UserBase
from ....model.settings import Settings
from ....model.descriptors import FieldDescriptor
from ....model.descriptors import EntityEventContext, FieldDescriptor
from ....model.language import LanguageBase
from ....auth import authorize_command
from ....utils.main import (
@@ -281,6 +282,12 @@ async def process_field_edit_callback(message: Message | CallbackQuery, **kwargs
commit=True,
)
if entity_descriptor.on_created:
if iscoroutinefunction(entity_descriptor.on_created):
await entity_descriptor.on_created(new_entity, EntityEventContext(db_session=db_session, app=app))
else:
entity_descriptor.on_created(new_entity, EntityEventContext(db_session=db_session, app=app))
form_name = (
callback_data.form_params.split("&")[0]
if callback_data.form_params
@@ -325,6 +332,13 @@ async def process_field_edit_callback(message: Message | CallbackQuery, **kwargs
setattr(entity, key, value)
await db_session.commit()
await db_session.refresh(entity)
if entity_descriptor.on_updated:
if iscoroutinefunction(entity_descriptor.on_updated):
await entity_descriptor.on_updated(entity, EntityEventContext(db_session=db_session, app=app))
else:
entity_descriptor.on_updated(entity, EntityEventContext(db_session=db_session, app=app))
elif callback_data.context == CommandContext.COMMAND_FORM:
clear_state(state_data=state_data)

View File

@@ -1,3 +1,4 @@
from inspect import iscoroutinefunction
from aiogram import Router, F
from aiogram.fsm.context import FSMContext
from aiogram.types import CallbackQuery, InlineKeyboardButton
@@ -5,6 +6,8 @@ from aiogram.utils.keyboard import InlineKeyboardBuilder
from sqlmodel.ext.asyncio.session import AsyncSession
from typing import TYPE_CHECKING
from qbot.model.descriptors import EntityEventContext
from ..context import ContextData, CallbackCommand
from ....model.user import UserBase
from ....model.settings import Settings
@@ -47,10 +50,18 @@ async def entity_delete_callback(query: CallbackQuery, **kwargs):
)
if callback_data.data == "yes":
await entity_descriptor.type_.remove(
entity = await entity_descriptor.type_.remove(
session=db_session, id=int(callback_data.entity_id), commit=True
)
if entity_descriptor.on_deleted:
if iscoroutinefunction(entity_descriptor.on_created):
await entity_descriptor.on_deleted(entity, EntityEventContext(db_session=db_session, app=app))
else:
entity_descriptor.on_deleted(entity, EntityEventContext(db_session=db_session, app=app))
await route_callback(message=query, **kwargs)
elif not callback_data.data:

View File

@@ -31,7 +31,7 @@ class Config(BaseSettings):
def API_DOMAIN(self) -> str:
if self.ENVIRONMENT == "local":
return self.DOMAIN
return f"api.{self.DOMAIN}"
return f"{self.DOMAIN}"
@computed_field
@property
@@ -39,7 +39,7 @@ class Config(BaseSettings):
if self.USE_NGROK:
return self.NGROK_URL
return (
f"{'http' if self.ENVIRONMENT == 'local' else 'https'}://{self.API_DOMAIN}"
f"https://{self.API_DOMAIN}"
)
API_PORT: int = 8000

View File

@@ -163,6 +163,9 @@ class _BaseEntityDescriptor:
EntityPermission.DELETE_ALL: [RoleBase.SUPER_USER],
}
)
on_created: Callable[["BotEntity", "EntityEventContext"], None] | None = None
on_deleted: Callable[["BotEntity", "EntityEventContext"], None] | None = None
on_updated: Callable[["BotEntity", "EntityEventContext"], None] | None = None
@dataclass(kw_only=True)
@@ -197,6 +200,12 @@ class CommandCallbackContext[UT: UserBase]:
kwargs: dict[str, Any] = field(default_factory=dict)
@dataclass(kw_only=True)
class EntityEventContext:
db_session: AsyncSession
app: "QBotApp"
@dataclass(kw_only=True)
class BotCommand:
name: str