import json from pathlib import Path from typing import Literal import platformdirs from loguru import logger from pydantic import Field from pydantic_settings import BaseSettings, SettingsConfigDict class Settings(BaseSettings): host: str = Field("irc.chat.twitch.tv", alias="Host", serialization_alias="Host") port: int = Field(6667, alias="Port", serialization_alias="Port") channel: str = Field(..., alias="Channel", serialization_alias="Channel") nickname: str = Field(..., alias="Nickname", serialization_alias="Nickname") authentication: str = Field( ..., alias="Authentication", serialization_alias="Authentication", ) denied_users: list[str] = Field( [ "StreamElements", "Nightbot", "Moobot", "Marbiebot", ], alias="DeniedUsers", serialization_alias="DeniedUsers", ) banned_words: list[str] = Field( default_factory=list, alias="BannedWords", serialization_alias="BannedWords", ) mods: list[str] = Field( default_factory=list, alias="Mods", serialization_alias="Mods", ) cooldown: int = Field(210, alias="Cooldown", serialization_alias="Cooldown") key_length: int = Field(2, alias="KeyLength", serialization_alias="KeyLength") max_sentence_length: int = Field( 25, alias="MaxSentenceWordAmount", serialization_alias="MaxSentenceWordAmount", ) min_sentence_length: int = Field( -1, alias="MinSentenceWordAmount", serialization_alias="MinSentenceWordAmount", ) help_message_timer: int = Field( 60 * 60 * 5, alias="HelpMessageTimer", serialization_alias="HelpMessageTimer", ) automatic_generation_timer: int = Field( -1, alias="AutomaticGenerationTimer", serialization_alias="AutomaticGenerationTimer", ) whisper_cooldown: bool = Field( True, alias="WhisperCooldown", serialization_alias="WhisperCooldown", ) enable_generate_command: bool = Field( True, alias="EnableGenerateCommand", serialization_alias="EnableGenerateCommand", ) sentence_separator: str = Field( " - ", alias="SentenceSeparator", serialization_alias="SentenceSeparator", ) allow_generate_params: bool = Field( True, alias="AllowGenerateParams", serialization_alias="AllowGenerateParams", ) log_level: Literal[ "CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG", "TRACE", ] = Field("DEBUG", alias="LogLevel") model_config = SettingsConfigDict(extra="ignore") @property def channel_name(self): return self.channel.replace("#", "").lower() @classmethod def read(cls, filepath: Path | None = None) -> "Settings": if not filepath: filepath = ( platformdirs.user_config_path("markovbot_gui", ensure_exists=True) / "settings.json" ) with filepath.open("r") as f: data = json.load(f) return Settings(**data) def write(self, filepath: Path | None = None): if not filepath: filepath = ( platformdirs.user_config_path("markovbot_gui", ensure_exists=True) / "settings.json" ) with filepath.open("w") as f: logger.info(f"Writing current settings to {filepath}") json.dump(self.model_dump(by_alias=True), f, indent=4)