103 lines
3.0 KiB
Python
103 lines
3.0 KiB
Python
from datetime import datetime
|
|
|
|
from pydantic import BaseModel, Field, root_validator, validator
|
|
|
|
from app.config import settings
|
|
|
|
|
|
class HTMLGenerateRequest(BaseModel):
|
|
html_content: str = Field(
|
|
...,
|
|
description="Required HTML content or HTML fragment.",
|
|
)
|
|
title: str | None = Field(
|
|
default=None,
|
|
max_length=120,
|
|
description="Optional page title shown in the generated HTML document.",
|
|
)
|
|
source: str | None = Field(
|
|
default=None,
|
|
max_length=80,
|
|
description="Optional source identifier such as a Tencent agent name.",
|
|
)
|
|
request_id: str | None = Field(
|
|
default=None,
|
|
max_length=120,
|
|
description="Optional trace id used for debugging and log correlation.",
|
|
)
|
|
ttl_days: int | None = Field(
|
|
default=None,
|
|
ge=1,
|
|
description="Optional retention days for the file.",
|
|
)
|
|
|
|
@root_validator(pre=True)
|
|
def normalize_aliases(cls, values: dict) -> dict:
|
|
if isinstance(values.get("body"), dict):
|
|
merged_values = dict(values["body"])
|
|
for key, value in values.items():
|
|
if key != "body" and key not in merged_values:
|
|
merged_values[key] = value
|
|
values = merged_values
|
|
|
|
alias_map = {
|
|
"html": "html_content",
|
|
"content": "html_content",
|
|
"expire_days": "ttl_days",
|
|
}
|
|
|
|
for alias, target in alias_map.items():
|
|
if target not in values and alias in values:
|
|
values[target] = values[alias]
|
|
|
|
return values
|
|
|
|
@validator("html_content")
|
|
def validate_html_content(cls, value: str) -> str:
|
|
content = value.strip()
|
|
if not content:
|
|
raise ValueError("html_content cannot be empty")
|
|
|
|
if len(content.encode("utf-8")) > settings.max_html_length:
|
|
raise ValueError(
|
|
f"html_content exceeds the limit of {settings.max_html_length} bytes"
|
|
)
|
|
|
|
return content
|
|
|
|
@validator("title", "source", "request_id")
|
|
def normalize_optional_text(cls, value: str | None) -> str | None:
|
|
if value is None:
|
|
return None
|
|
|
|
normalized = value.strip()
|
|
return normalized or None
|
|
|
|
@validator("ttl_days")
|
|
def validate_ttl_days(cls, value: int | None) -> int | None:
|
|
if value is None:
|
|
return None
|
|
|
|
if value > settings.max_retention_days:
|
|
raise ValueError(
|
|
f"ttl_days cannot be greater than {settings.max_retention_days}"
|
|
)
|
|
|
|
return value
|
|
|
|
class Config:
|
|
extra = "ignore"
|
|
|
|
|
|
class HTMLGenerateResponse(BaseModel):
|
|
message: str
|
|
unique_id: str
|
|
url: str = Field(description="Direct URL that serves the generated HTML content.")
|
|
query_url: str = Field(description="Metadata URL for querying the generated record.")
|
|
title: str | None = None
|
|
source: str | None = None
|
|
request_id: str | None = None
|
|
size_bytes: int
|
|
created_at: datetime
|
|
expires_at: datetime
|