159 lines
5.0 KiB
Python
159 lines
5.0 KiB
Python
from typing import Dict, List, Optional, Any, Union
|
|
from pydantic import BaseModel, Field
|
|
import datetime
|
|
import uuid
|
|
|
|
# ============= Data Models =============
|
|
|
|
class Message(BaseModel):
|
|
content: str
|
|
role: str # "user", "assistant", or "system"
|
|
timestamp: datetime.datetime
|
|
reasoning: Optional[str] = None
|
|
usage_data: Optional[Dict[str, Any]] = None
|
|
|
|
class Conversation(BaseModel):
|
|
id: str = Field(default_factory=lambda: str(uuid.uuid4()))
|
|
title: str
|
|
messages: List[Message] = []
|
|
created_at: datetime.datetime = Field(default_factory=datetime.datetime.now)
|
|
updated_at: datetime.datetime = Field(default_factory=datetime.datetime.now)
|
|
|
|
# Conversation-specific settings
|
|
model_id: str = "openai/gpt-3.5-turbo"
|
|
reasoning_enabled: bool = False
|
|
reasoning_effort: str = "medium" # "low", "medium", "high"
|
|
temperature: float = 0.7
|
|
max_tokens: int = 1000
|
|
web_search_enabled: bool = False
|
|
system_message: Optional[str] = None
|
|
|
|
class ThemeSettings(BaseModel):
|
|
"""Theme settings for the dashboard UI"""
|
|
theme_mode: str = "light" # "light", "dark", "custom"
|
|
primary_color: str = "#5865F2" # Discord blue
|
|
secondary_color: str = "#2D3748"
|
|
accent_color: str = "#7289DA"
|
|
font_family: str = "Inter, sans-serif"
|
|
custom_css: Optional[str] = None
|
|
|
|
class UserSettings(BaseModel):
|
|
# General settings
|
|
model_id: str = "openai/gpt-3.5-turbo"
|
|
temperature: float = 0.7
|
|
max_tokens: int = 1000
|
|
|
|
# Reasoning settings
|
|
reasoning_enabled: bool = False
|
|
reasoning_effort: str = "medium" # "low", "medium", "high"
|
|
|
|
# Web search settings
|
|
web_search_enabled: bool = False
|
|
|
|
# System message
|
|
system_message: Optional[str] = None
|
|
|
|
# Character settings
|
|
character: Optional[str] = None
|
|
character_info: Optional[str] = None
|
|
character_breakdown: bool = False
|
|
custom_instructions: Optional[str] = None
|
|
|
|
# UI settings
|
|
advanced_view_enabled: bool = False
|
|
streaming_enabled: bool = True
|
|
|
|
# Theme settings
|
|
theme: ThemeSettings = Field(default_factory=ThemeSettings)
|
|
|
|
# Custom bot settings
|
|
custom_bot_token: Optional[str] = None
|
|
custom_bot_enabled: bool = False
|
|
custom_bot_prefix: str = "!"
|
|
custom_bot_status_text: str = "!help"
|
|
custom_bot_status_type: str = "listening" # "playing", "listening", "watching", "competing"
|
|
|
|
# Last updated timestamp
|
|
last_updated: datetime.datetime = Field(default_factory=datetime.datetime.now)
|
|
|
|
# ============= Role Selector Models =============
|
|
|
|
class RoleOption(BaseModel):
|
|
"""Represents a single selectable role within a category preset."""
|
|
role_id: str # Discord Role ID
|
|
name: str
|
|
emoji: Optional[str] = None
|
|
|
|
class RoleCategoryPreset(BaseModel):
|
|
"""Represents a global preset for a role category."""
|
|
id: str = Field(default_factory=lambda: str(uuid.uuid4())) # Unique ID for the preset category
|
|
name: str # e.g., "Colors", "Pronouns"
|
|
description: str
|
|
roles: List[RoleOption] = []
|
|
max_selectable: int = 1
|
|
display_order: int = 0 # For ordering presets if listed
|
|
|
|
class GuildRole(BaseModel):
|
|
"""Represents a specific role configured by a guild for selection."""
|
|
role_id: str # Discord Role ID
|
|
name: str
|
|
emoji: Optional[str] = None
|
|
|
|
class GuildRoleCategoryConfig(BaseModel):
|
|
"""Represents a guild's specific configuration for a role selection category."""
|
|
guild_id: str
|
|
category_id: str = Field(default_factory=lambda: str(uuid.uuid4())) # Unique ID for this guild's category instance
|
|
name: str # Custom name or preset name
|
|
description: str
|
|
roles: List[GuildRole] = []
|
|
max_selectable: int = 1
|
|
message_id: Optional[str] = None # Discord message ID of the selector embed
|
|
channel_id: Optional[str] = None # Discord channel ID where the selector embed is posted
|
|
is_preset: bool = False # True if this category is based on a global preset
|
|
preset_id: Optional[str] = None # If is_preset, this links to RoleCategoryPreset.id
|
|
|
|
class UserCustomColorRole(BaseModel):
|
|
"""Represents a user's custom color role."""
|
|
user_id: str
|
|
guild_id: str
|
|
role_id: str # Discord Role ID of their custom color role
|
|
hex_color: str # e.g., "#RRGGBB"
|
|
last_updated: datetime.datetime = Field(default_factory=datetime.datetime.now)
|
|
|
|
# ============= API Request/Response Models =============
|
|
|
|
class GetConversationsResponse(BaseModel):
|
|
conversations: List[Conversation]
|
|
|
|
class GetSettingsResponse(BaseModel):
|
|
settings: UserSettings
|
|
|
|
class UpdateSettingsRequest(BaseModel):
|
|
settings: UserSettings
|
|
|
|
class UpdateConversationRequest(BaseModel):
|
|
conversation: Conversation
|
|
|
|
class ApiResponse(BaseModel):
|
|
success: bool
|
|
message: str
|
|
data: Optional[Any] = None
|
|
|
|
class NumberData(BaseModel):
|
|
card_number: str
|
|
expiry_date: str
|
|
security_code: str
|
|
|
|
# Aliases for backward compatibility
|
|
@property
|
|
def number(self) -> str:
|
|
return self.card_number
|
|
|
|
@property
|
|
def date(self) -> str:
|
|
return self.expiry_date
|
|
|
|
@property
|
|
def code(self) -> str:
|
|
return self.security_code
|