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:
Andre Beging
2025-10-07 13:39:07 +02:00
parent c7f694d820
commit 1204f5dcde
11 changed files with 559 additions and 134 deletions

View File

@@ -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):