feat: Enhance hook management and session handling
- Update hook model to include last_triggered_at field. - Modify API endpoints to support updating hooks with new fields. - Implement session management UI improvements with toggle functionality. - Add new JavaScript functions for better session detail visibility. - Refactor hook storage logic to handle last triggered timestamps. - Introduce new favicon and logo for branding. - Update styles for improved layout and user experience. - Enhance tests to cover new functionality and ensure reliability.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
from pydantic import BaseModel, Field, field_validator, model_validator
|
||||
|
||||
|
||||
class HookCreate(BaseModel):
|
||||
@@ -14,6 +14,7 @@ class HookRead(BaseModel):
|
||||
message: str
|
||||
chat_id: str
|
||||
created_at: datetime
|
||||
last_triggered_at: Optional[datetime] = None
|
||||
|
||||
@property
|
||||
def action_path(self) -> str:
|
||||
@@ -24,14 +25,60 @@ class HookResponse(HookRead):
|
||||
action_url: str
|
||||
|
||||
|
||||
class HookUpdateId(BaseModel):
|
||||
hook_id: str = Field(
|
||||
...,
|
||||
class HookUpdate(BaseModel):
|
||||
hook_id: Optional[str] = Field(
|
||||
default=None,
|
||||
min_length=3,
|
||||
max_length=64,
|
||||
pattern=r"^[A-Za-z0-9_-]+$",
|
||||
description="New hook identifier",
|
||||
)
|
||||
chat_id: Optional[str] = Field(
|
||||
default=None,
|
||||
min_length=1,
|
||||
description="Updated target chat ID or username",
|
||||
)
|
||||
message: Optional[str] = Field(
|
||||
default=None,
|
||||
min_length=1,
|
||||
description="Updated message body supporting Markdown",
|
||||
)
|
||||
|
||||
@model_validator(mode="after")
|
||||
def ensure_any_field(cls, values: "HookUpdate") -> "HookUpdate":
|
||||
if values.hook_id is None and values.chat_id is None and values.message is None:
|
||||
raise ValueError("Provide at least one field to update")
|
||||
return values
|
||||
|
||||
@field_validator("hook_id", mode="before")
|
||||
@classmethod
|
||||
def normalize_hook_id(cls, value: Optional[str]) -> Optional[str]:
|
||||
if value is None:
|
||||
return None
|
||||
trimmed = value.strip()
|
||||
if not trimmed:
|
||||
raise ValueError("Hook ID cannot be empty")
|
||||
return trimmed
|
||||
|
||||
@field_validator("chat_id", mode="before")
|
||||
@classmethod
|
||||
def normalize_chat_id(cls, value: Optional[str]) -> Optional[str]:
|
||||
if value is None:
|
||||
return None
|
||||
trimmed = value.strip()
|
||||
if not trimmed:
|
||||
raise ValueError("Chat ID cannot be empty")
|
||||
return trimmed
|
||||
|
||||
@field_validator("message", mode="before")
|
||||
@classmethod
|
||||
def normalize_message(cls, value: Optional[str]) -> Optional[str]:
|
||||
if value is None:
|
||||
return None
|
||||
stripped = value.strip()
|
||||
if not stripped:
|
||||
raise ValueError("Message cannot be empty")
|
||||
return stripped
|
||||
|
||||
|
||||
class LoginStartRequest(BaseModel):
|
||||
|
||||
Reference in New Issue
Block a user