from pydantic import BaseModel, Field, field_validator from typing import List, Optional, Dict, Any from llama_index.core.llms import MessageRole from datetime import datetime import re import pytz jakarta_tz = pytz.timezone("Asia/Jakarta") class PasswordValidator: @staticmethod def validate(password: str) -> str: if len(password) < 8 or len(password) > 32: raise ValueError("Password must be between 8 and 32 characters long") if not re.search(r"[A-Z]", password): raise ValueError("Password must contain at least one uppercase letter") if not re.search(r"[a-z]", password): raise ValueError("Password must contain at least one lowercase letter") if not re.search(r"\d", password): raise ValueError("Password must contain at least one digit") if not re.search(r'[!@#$%^&*(),.?":{}|<>]', password): raise ValueError("Password must contain at least one special character") return password class CreateUserRequest(BaseModel): name: str username: str email: str password: str role_id: int = 2 @field_validator("password") def validate_password(cls, password): return PasswordValidator.validate(password) class RoleCreate(BaseModel): name: str class RoleUpdate(BaseModel): name: str class LoginRequest(BaseModel): email: str password: str class UserVerification(BaseModel): password: str new_password: str = Field(min_length=6) @field_validator("new_password") def validate_new_password(cls, new_password): return PasswordValidator.validate(new_password) class Token(BaseModel): access_token: str token_type: str class MetadataRequest(BaseModel): title: str category_id: int author: str year: int publisher: str class MetadataResponse(BaseModel): id : int title: str author: str category: str # Changed to reflect the actual category name category_id : int year: int publisher: str thumbnail: Optional[Any] # Make thumbnail optional class Config: from_attributes = True class DeleteById(BaseModel): id: str class UserPromptRequest(BaseModel): prompt: str streaming: bool class BotMetaCreate(BaseModel): metadata_id: List[int] # List of integers for metadata_id class BotCreateRequest(BaseModel): name: str class BotResponse(BaseModel): role: str = "assistant" content: str metadata: List scores: List class BotResponseStreaming(BaseModel): role: str = "assistant" content: Optional[str] = None completed_content: Optional[str] = None reference: Optional[str] = None metadata: Optional[Dict] = None score: Optional[float] = None class TestStreaming(BaseModel): role: str = "assistant" content: str class ChatMessage(BaseModel): """Chat message.""" role: MessageRole = MessageRole.ASSISTANT content: Optional[Any] = "" metadata: Optional[List[Any]] = None timestamp : Optional[datetime] = datetime.now(jakarta_tz) payment: Optional[str] = Field(default=None) class ChatHistory(BaseModel): messages: List[ChatMessage] class CategoryCreate(BaseModel): category_name: str