feat(global): init structure

This commit is contained in:
h
2025-07-01 12:55:01 +03:00
commit 1b21f23294
37 changed files with 1208 additions and 0 deletions

2
src/utils/__init__.py Normal file
View File

@@ -0,0 +1,2 @@
from .env import env
from .logging import logger

23
src/utils/config.py Normal file
View File

@@ -0,0 +1,23 @@
from pymongo import MongoClient
from utils.db.models.config import DynamicConfig, DynamicConfigBase
from . import env
def load_config() -> DynamicConfigBase:
client = MongoClient(env.db.connection_url)
db = client[env.db.db_name]
config_dict = db.config.find_one()
if config_dict is None:
return DynamicConfigBase()
config_dict.pop("_id", None)
return DynamicConfigBase.model_validate(config_dict)
dconfig = DynamicConfig.get_or_create
config: DynamicConfigBase = load_config()

19
src/utils/db/__init__.py Normal file
View File

@@ -0,0 +1,19 @@
from beanie import init_beanie
from motor.motor_asyncio import AsyncIOMotorClient
from utils.env import env
client = AsyncIOMotorClient(env.db.connection_url)
async def init_db():
from .models import (
DynamicConfig,
)
await init_beanie(
database=client[env.db.db_name],
document_models=[
DynamicConfig,
],
)

View File

@@ -0,0 +1 @@
from .config import DynamicConfig

View File

@@ -0,0 +1,27 @@
from beanie import Document
from pydantic import BaseModel, Field
class BotConfig(BaseModel):
admins: list[int] = []
class DynamicConfigBase(BaseModel):
bot: BotConfig = Field(default_factory=BotConfig)
class DynamicConfig(DynamicConfigBase, Document):
class Settings:
name = "config"
async def save(self): # noqa
await super().save() # noqa
@classmethod
async def get_or_create(cls):
config = await cls.find_one()
if not config:
config = cls()
await config.save()
return config

42
src/utils/env.py Normal file
View File

@@ -0,0 +1,42 @@
from pydantic import SecretStr
from pydantic_settings import BaseSettings, SettingsConfigDict
class BotSettings(BaseSettings):
token: SecretStr
class DatabaseSettings(BaseSettings):
host: str = "mongodb"
port: int = 27017
user: SecretStr = "user"
password: SecretStr = "password"
db_name: str = "prod"
connection_params: str = "?authSource=admin"
scripts_connection_url: str = "mongodb://user:password@localhost:27017/"
@property
def connection_url(self) -> str:
return f"mongodb://{self.user.get_secret_value()}:{self.password.get_secret_value()}@{self.host}:{self.port}/{self.db_name}{self.connection_params}"
class LogSettings(BaseSettings):
level: str = "INFO"
show_time: bool = False
console_width: int = 150
class Settings(BaseSettings):
bot: BotSettings
db: DatabaseSettings
log: LogSettings
model_config = SettingsConfigDict(
case_sensitive=False,
env_file=".env",
env_nested_delimiter="__",
extra="ignore",
)
env = Settings() # noqa

37
src/utils/logging.py Normal file
View File

@@ -0,0 +1,37 @@
import logging
from rich.console import Console
from rich.logging import RichHandler
from . import env
console = Console(
width=env.log.console_width,
color_system="auto",
force_terminal=True,
)
def setup_logging():
from aiogram.dispatcher import router
from dishka.integrations import aiogram
logging.basicConfig(
level=env.log.level,
format=None, # noqa
datefmt=None,
handlers=[
RichHandler(
console=console,
markup=True,
rich_tracebacks=True,
tracebacks_show_locals=True,
omit_repeated_times=False,
show_time=env.log.show_time,
tracebacks_suppress=[router, aiogram],
)
],
)
logger = logging.getLogger(__name__)