new bot structure
This commit is contained in:
3
.env.example
Normal file
3
.env.example
Normal file
@@ -0,0 +1,3 @@
|
||||
ENV_FOR_DYNACONF=production
|
||||
|
||||
BOT_TOKEN=
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,4 +1,6 @@
|
||||
__pycache__
|
||||
.venv
|
||||
.env
|
||||
*.db
|
||||
*.db
|
||||
# Ignore dynaconf secret files
|
||||
.secrets.*
|
||||
|
||||
3
app/bot/__init__.py
Normal file
3
app/bot/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from .bot import main
|
||||
|
||||
__all__ = ["main"]
|
||||
@@ -2,21 +2,19 @@ import asyncio
|
||||
|
||||
from aiogram import Bot, Dispatcher
|
||||
from aiogram_dialog import setup_dialogs
|
||||
from bestconfig import Config
|
||||
|
||||
from app.dialogs import dialogs_router
|
||||
from app.handlers import handlers_router
|
||||
from app.bot.dialogs.flows import dialogs_router
|
||||
from app.bot.handlers.commands import commands_router
|
||||
from config.config import settings
|
||||
|
||||
cfg = Config()
|
||||
|
||||
bot = Bot(token=cfg.get("bot_token"))
|
||||
bot = Bot(token=settings.bot_token)
|
||||
dp = Dispatcher()
|
||||
|
||||
|
||||
async def main():
|
||||
dp.include_router(handlers_router)
|
||||
dp.include_router(dialogs_router)
|
||||
setup_dialogs(dp)
|
||||
dp.include_router(commands_router)
|
||||
dp.include_router(dialogs_router)
|
||||
await dp.start_polling(bot)
|
||||
|
||||
|
||||
8
app/bot/dialogs/flows/__init__.py
Normal file
8
app/bot/dialogs/flows/__init__.py
Normal file
@@ -0,0 +1,8 @@
|
||||
from aiogram import Router
|
||||
|
||||
from .admin import admin_router
|
||||
from .user import user_router
|
||||
|
||||
dialogs_router = Router(name="dialogs")
|
||||
dialogs_router.include_router(admin_router)
|
||||
dialogs_router.include_router(user_router)
|
||||
3
app/bot/dialogs/flows/admin/__init__.py
Normal file
3
app/bot/dialogs/flows/admin/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from aiogram import Router
|
||||
|
||||
admin_router = Router(name="admin dialogs")
|
||||
6
app/bot/dialogs/flows/user/__init__.py
Normal file
6
app/bot/dialogs/flows/user/__init__.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from aiogram import Router
|
||||
|
||||
from .start.dialogs import start_dialog
|
||||
|
||||
user_router = Router(name="user")
|
||||
user_router.include_router(start_dialog)
|
||||
14
app/bot/dialogs/flows/user/start/dialogs.py
Normal file
14
app/bot/dialogs/flows/user/start/dialogs.py
Normal file
@@ -0,0 +1,14 @@
|
||||
from aiogram_dialog import Dialog, Window
|
||||
from aiogram_dialog.widgets.text import Format
|
||||
|
||||
from app.bot.dialogs.widgets.getters import username_getter
|
||||
|
||||
from .states import StartSG
|
||||
|
||||
start_dialog = Dialog(
|
||||
Window(
|
||||
Format("Hello, {username}"),
|
||||
getter=username_getter,
|
||||
state=StartSG.start,
|
||||
)
|
||||
)
|
||||
5
app/bot/dialogs/flows/user/start/states.py
Normal file
5
app/bot/dialogs/flows/user/start/states.py
Normal file
@@ -0,0 +1,5 @@
|
||||
from aiogram.fsm.state import State, StatesGroup
|
||||
|
||||
|
||||
class StartSG(StatesGroup):
|
||||
start = State()
|
||||
@@ -4,5 +4,5 @@ from aiogram_dialog import DialogManager
|
||||
|
||||
async def username_getter(
|
||||
dialog_manager: DialogManager, event_from_user: User, **kwargs
|
||||
):
|
||||
) -> dict[str, str]:
|
||||
return {"username": event_from_user.username}
|
||||
@@ -3,10 +3,10 @@ from aiogram.filters import CommandStart
|
||||
from aiogram.types import Message
|
||||
from aiogram_dialog import DialogManager
|
||||
|
||||
from app.dialogs.user_dialog import StartSG
|
||||
from app.bot.dialogs.flows.user.start.states import StartSG
|
||||
|
||||
router = Router(name="user_handlers")
|
||||
commands_router = Router(name="commands_router")
|
||||
|
||||
@router.message(CommandStart())
|
||||
@commands_router.message(CommandStart())
|
||||
async def command_start_process(message: Message, dialog_manager: DialogManager):
|
||||
await dialog_manager.start(state=StartSG.start)
|
||||
@@ -1,6 +0,0 @@
|
||||
from aiogram import Router
|
||||
|
||||
from .user_dialog import router as user_router
|
||||
|
||||
dialogs_router = Router(name="dialogs")
|
||||
dialogs_router.include_router(user_router)
|
||||
@@ -1,22 +0,0 @@
|
||||
from aiogram import Router
|
||||
from aiogram.fsm.state import State, StatesGroup
|
||||
from aiogram_dialog import Dialog, DialogManager, StartMode, Window
|
||||
from aiogram_dialog.widgets.text import Format
|
||||
|
||||
from app.utils.getters import username_getter
|
||||
|
||||
|
||||
class StartSG(StatesGroup):
|
||||
start = State()
|
||||
|
||||
|
||||
start_dialog = Dialog(
|
||||
Window(
|
||||
Format("Hello, {username}"),
|
||||
getter=username_getter,
|
||||
state=StartSG.start
|
||||
)
|
||||
)
|
||||
|
||||
router = Router(name="user_dialogs")
|
||||
router.include_router(start_dialog)
|
||||
@@ -1,6 +0,0 @@
|
||||
from aiogram import Router
|
||||
|
||||
from .user_handlers import router as user_router
|
||||
|
||||
handlers_router = Router(name="handlers")
|
||||
handlers_router.include_router(user_router)
|
||||
12
config/config.py
Normal file
12
config/config.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from dynaconf import Dynaconf
|
||||
|
||||
settings = Dynaconf(
|
||||
envvar_prefix=False,
|
||||
environments=True,
|
||||
env_switcher="ENV_FOR_DYNACONF",
|
||||
settings_files=["settings.toml"],
|
||||
load_dotenv=True
|
||||
)
|
||||
|
||||
# `envvar_prefix` = export envvars with `export DYNACONF_FOO=bar`.
|
||||
# `settings_files` = Load these files in the order.
|
||||
1
config/settings.toml
Normal file
1
config/settings.toml
Normal file
@@ -0,0 +1 @@
|
||||
[DEVELOPMENT]
|
||||
5
main.py
Normal file
5
main.py
Normal file
@@ -0,0 +1,5 @@
|
||||
import asyncio
|
||||
|
||||
from app.bot import main
|
||||
|
||||
asyncio.run(main())
|
||||
@@ -6,6 +6,7 @@ dependencies = [
|
||||
"aiogram>=3.22.0",
|
||||
"aiogram-dialog>=2.4.0",
|
||||
"bestconfig>=1.3.6",
|
||||
"dynaconf>=3.2.11",
|
||||
"psycopg>=3.2.10",
|
||||
"sqlalchemy>=2.0.43",
|
||||
]
|
||||
|
||||
11
uv.lock
generated
11
uv.lock
generated
@@ -163,6 +163,15 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e5/48/1549795ba7742c948d2ad169c1c8cdbae65bc450d6cd753d124b17c8cd32/certifi-2025.8.3-py3-none-any.whl", hash = "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5", size = 161216, upload-time = "2025-08-03T03:07:45.777Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dynaconf"
|
||||
version = "3.2.11"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/62/eb/e9d1249ff56b11e63fd8c7d0fcc1f94704e21693c16862bf0ebfb07bd61a/dynaconf-3.2.11.tar.gz", hash = "sha256:4cfc6a730c533bf1a1d0bf266ae202133a22236bb3227d23eff4b8542d4034a5", size = 234694, upload-time = "2025-05-06T15:44:59.16Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/36/64/580c74003a356c5662e7b1da43ecd7cbda6e8f970c87b30c5a654c8ccb53/dynaconf-3.2.11-py2.py3-none-any.whl", hash = "sha256:660de90879d4da236f79195692a7d197957224d7acf922bcc6899187dc7b4a27", size = 236536, upload-time = "2025-05-06T15:44:56.18Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "frozenlist"
|
||||
version = "1.7.0"
|
||||
@@ -607,6 +616,7 @@ dependencies = [
|
||||
{ name = "aiogram" },
|
||||
{ name = "aiogram-dialog" },
|
||||
{ name = "bestconfig" },
|
||||
{ name = "dynaconf" },
|
||||
{ name = "psycopg" },
|
||||
{ name = "sqlalchemy" },
|
||||
]
|
||||
@@ -616,6 +626,7 @@ requires-dist = [
|
||||
{ name = "aiogram", specifier = ">=3.22.0" },
|
||||
{ name = "aiogram-dialog", specifier = ">=2.4.0" },
|
||||
{ name = "bestconfig", specifier = ">=1.3.6" },
|
||||
{ name = "dynaconf", specifier = ">=3.2.11" },
|
||||
{ name = "psycopg", specifier = ">=3.2.10" },
|
||||
{ name = "sqlalchemy", specifier = ">=2.0.43" },
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user