[dev] basic project structure

This commit is contained in:
h
2025-03-28 16:48:44 +02:00
commit 1a5fd5977e
29 changed files with 930 additions and 0 deletions

57
src/bot/__init__.py Normal file
View File

@@ -0,0 +1,57 @@
import contextlib
from utils.logging import setup_logging, logger
from dishka import make_async_container
from dishka.integrations.aiogram import setup_dishka, AiogramProvider
from beanie import init_beanie
setup_logging()
async def setup_db():
from .common import db
await init_beanie(
database=db,
document_models=[
]
)
logger.info("Database connection established")
async def runner():
from . import callbacks, handlers
from .common import bot, dp
await setup_db()
container = make_async_container(
AiogramProvider(),
)
setup_dishka(
container=container,
router=dp,
auto_inject=True,
)
dp.include_routers(
handlers.router,
callbacks.router,
)
await bot.delete_webhook(drop_pending_updates=True)
await dp.start_polling(bot)
def main():
import asyncio
logger.info("Starting...")
with contextlib.suppress(KeyboardInterrupt):
asyncio.run(runner())
logger.info("[red]Stopped.[/]")

5
src/bot/__main__.py Normal file
View File

@@ -0,0 +1,5 @@
from . import main
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,3 @@
from aiogram import Router
router = Router()

15
src/bot/common.py Normal file
View File

@@ -0,0 +1,15 @@
from aiogram import Bot, Dispatcher
from aiogram.client.default import DefaultBotProperties
from aiogram.fsm.storage.mongo import MongoStorage
import motor.motor_asyncio
from utils import env
bot = Bot(token=env.bot.token.get_secret_value(), default=DefaultBotProperties(parse_mode="HTML"))
dp = Dispatcher(storage=MongoStorage.from_url(env.db.connection_url))
motor_client = motor.motor_asyncio.AsyncIOMotorClient(env.db.connection_url)
db = motor_client[env.db.db_name]
__all__ = ["bot", "dp", "motor_client", "db"]

View File

@@ -0,0 +1,13 @@
from aiogram import Router
from . import (
initialize,
start,
)
router = Router()
router.include_routers(
initialize.router,
start.router,
)

View File

@@ -0,0 +1 @@
from .initializer import router

View File

@@ -0,0 +1,9 @@
from aiogram import Bot, Router
from utils.logging import logger
router = Router()
@router.startup()
async def startup(bot: Bot):
logger.info(f"[green]Started as[/] @{(await bot.me()).username}")

View File

@@ -0,0 +1 @@
from .start import router

View File

@@ -0,0 +1,10 @@
from aiogram import Bot, Router, types
from aiogram.filters import CommandStart
from utils.logging import logger
router = Router()
@router.message(CommandStart)
async def on_start(message: types.Message):
await message.reply("nya")

View File

View File

View File

View File

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

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

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

9
src/utils/db/migrate.py Normal file
View File

@@ -0,0 +1,9 @@
import asyncio
from utils import env
async def main():
print(env.db.host)
asyncio.run(main())

View File

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

@@ -0,0 +1,41 @@
from pydantic_settings import BaseSettings, SettingsConfigDict
from pydantic import SecretStr
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 = ""
@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

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

@@ -0,0 +1,38 @@
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__)