add user model, commands handler, router setup, and related dependencies
This commit is contained in:
parent
6ac3717ce2
commit
2a1f15fdf2
@ -46,4 +46,5 @@ dev = [
|
|||||||
"pre-commit>=4.2.0",
|
"pre-commit>=4.2.0",
|
||||||
"pyupgrade>=3.20.0",
|
"pyupgrade>=3.20.0",
|
||||||
"ruff>=0.11.13",
|
"ruff>=0.11.13",
|
||||||
|
"types-requests>=2.32.4.20250809",
|
||||||
]
|
]
|
||||||
|
|||||||
@ -4,8 +4,10 @@ import types
|
|||||||
def get_app_models_modules() -> list[types.ModuleType]:
|
def get_app_models_modules() -> list[types.ModuleType]:
|
||||||
from greek_lang.glossaries import models as glossaries_models
|
from greek_lang.glossaries import models as glossaries_models
|
||||||
from greek_lang.openai_manager import models as openai_manager_models
|
from greek_lang.openai_manager import models as openai_manager_models
|
||||||
|
from greek_lang.users import models as users_models
|
||||||
|
|
||||||
return [
|
return [
|
||||||
glossaries_models,
|
glossaries_models,
|
||||||
openai_manager_models,
|
openai_manager_models,
|
||||||
|
users_models,
|
||||||
]
|
]
|
||||||
|
|||||||
@ -0,0 +1,54 @@
|
|||||||
|
"""empty message
|
||||||
|
|
||||||
|
Revision ID: 747797032526
|
||||||
|
Revises: d30d80dee5a3
|
||||||
|
Create Date: 2025-08-16 17:53:23.785592
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
from typing import Sequence, Union
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision: str = "747797032526"
|
||||||
|
down_revision: Union[str, None] = "d30d80dee5a3"
|
||||||
|
branch_labels: Union[str, Sequence[str], None] = None
|
||||||
|
depends_on: Union[str, Sequence[str], None] = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade() -> None:
|
||||||
|
"""Upgrade schema."""
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.create_table(
|
||||||
|
"users",
|
||||||
|
sa.Column("id", sa.BigInteger(), nullable=False),
|
||||||
|
sa.Column("is_bot", sa.Boolean(), nullable=False),
|
||||||
|
sa.Column("first_name", sa.String(), nullable=True),
|
||||||
|
sa.Column("last_name", sa.String(), nullable=True),
|
||||||
|
sa.Column("username", sa.String(), nullable=True),
|
||||||
|
sa.Column("language_code", sa.String(length=8), nullable=True),
|
||||||
|
sa.Column("is_premium", sa.Boolean(), nullable=True),
|
||||||
|
sa.Column("added_to_attachment_menu", sa.Boolean(), nullable=True),
|
||||||
|
sa.Column(
|
||||||
|
"registered_at",
|
||||||
|
sa.DateTime(timezone=True),
|
||||||
|
server_default=sa.text("now()"),
|
||||||
|
nullable=False,
|
||||||
|
),
|
||||||
|
sa.PrimaryKeyConstraint("id", name=op.f("pk_users")),
|
||||||
|
)
|
||||||
|
op.create_index(op.f("ix_users_id"), "users", ["id"], unique=False)
|
||||||
|
op.create_index(op.f("ix_users_username"), "users", ["username"], unique=False)
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade() -> None:
|
||||||
|
"""Downgrade schema."""
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_index(op.f("ix_users_username"), table_name="users")
|
||||||
|
op.drop_index(op.f("ix_users_id"), table_name="users")
|
||||||
|
op.drop_table("users")
|
||||||
|
# ### end Alembic commands ###
|
||||||
@ -1,11 +1,8 @@
|
|||||||
import pydantic
|
import pydantic
|
||||||
from aiogram import Bot, Dispatcher, BaseMiddleware
|
from aiogram import Bot, Dispatcher, BaseMiddleware
|
||||||
from aiogram.enums import ParseMode
|
|
||||||
from aiogram.filters import CommandStart
|
|
||||||
from aiogram.fsm.storage.base import BaseStorage, DefaultKeyBuilder
|
from aiogram.fsm.storage.base import BaseStorage, DefaultKeyBuilder
|
||||||
from aiogram.fsm.storage.redis import RedisStorage
|
from aiogram.fsm.storage.redis import RedisStorage
|
||||||
from aiogram.types import BotCommandScopeAllPrivateChats, Message
|
from aiogram.types import BotCommandScopeAllPrivateChats
|
||||||
from aiogram_dialog import DialogManager, setup_dialogs
|
|
||||||
from dependency_injector.wiring import Provide, inject
|
from dependency_injector.wiring import Provide, inject
|
||||||
|
|
||||||
from ..configs.container import ConfigContainer
|
from ..configs.container import ConfigContainer
|
||||||
@ -26,14 +23,7 @@ def create_bot(
|
|||||||
|
|
||||||
|
|
||||||
async def create_dispatcher() -> Dispatcher:
|
async def create_dispatcher() -> Dispatcher:
|
||||||
async def start(message: Message, dialog_manager: DialogManager) -> None:
|
from .router import router as root_router
|
||||||
user = message.from_user
|
|
||||||
if user is None:
|
|
||||||
return
|
|
||||||
await message.answer(
|
|
||||||
text="TEST",
|
|
||||||
parse_mode=ParseMode.HTML,
|
|
||||||
)
|
|
||||||
|
|
||||||
fsm_storage = await create_fsm_storage()
|
fsm_storage = await create_fsm_storage()
|
||||||
|
|
||||||
@ -45,10 +35,7 @@ async def create_dispatcher() -> Dispatcher:
|
|||||||
for middleware in middlewares:
|
for middleware in middlewares:
|
||||||
dp.update.middleware(middleware)
|
dp.update.middleware(middleware)
|
||||||
|
|
||||||
dp.message.register(start, CommandStart())
|
dp.include_routers(root_router)
|
||||||
dp.business_message.register(start, CommandStart())
|
|
||||||
|
|
||||||
setup_dialogs(dp)
|
|
||||||
return dp
|
return dp
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
23
src/greek_lang/tg_bot/commands.py
Normal file
23
src/greek_lang/tg_bot/commands.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
from gettext import gettext
|
||||||
|
|
||||||
|
from aiogram import Router
|
||||||
|
from aiogram.enums import ParseMode
|
||||||
|
from aiogram.filters import CommandStart
|
||||||
|
from aiogram.types import Message
|
||||||
|
|
||||||
|
from greek_lang.users.manager import get_or_create_telegram_user
|
||||||
|
|
||||||
|
|
||||||
|
router = Router()
|
||||||
|
|
||||||
|
|
||||||
|
@router.message(CommandStart())
|
||||||
|
async def start(message: Message) -> None:
|
||||||
|
user = message.from_user
|
||||||
|
if user is None:
|
||||||
|
return
|
||||||
|
await get_or_create_telegram_user(user)
|
||||||
|
await message.answer(
|
||||||
|
text=gettext("Регистрация прошла.").format(user=user.full_name),
|
||||||
|
parse_mode=ParseMode.HTML,
|
||||||
|
)
|
||||||
8
src/greek_lang/tg_bot/router.py
Normal file
8
src/greek_lang/tg_bot/router.py
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
from aiogram import Router
|
||||||
|
|
||||||
|
from .commands import router as commands_router
|
||||||
|
|
||||||
|
router = Router()
|
||||||
|
router.include_routers(
|
||||||
|
commands_router,
|
||||||
|
)
|
||||||
0
src/greek_lang/users/__init__.py
Normal file
0
src/greek_lang/users/__init__.py
Normal file
39
src/greek_lang/users/manager.py
Normal file
39
src/greek_lang/users/manager.py
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
from aiogram.types import User
|
||||||
|
from dependency_injector.wiring import Provide, inject
|
||||||
|
from sqlalchemy.exc import IntegrityError
|
||||||
|
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker
|
||||||
|
|
||||||
|
from greek_lang.database.container import DatabaseContainer
|
||||||
|
from greek_lang.users.models import User as TgUser
|
||||||
|
|
||||||
|
|
||||||
|
@inject
|
||||||
|
async def get_or_create_telegram_user(
|
||||||
|
user: User,
|
||||||
|
db_session_maker: async_sessionmaker[AsyncSession] = Provide[
|
||||||
|
DatabaseContainer.async_session_maker
|
||||||
|
],
|
||||||
|
) -> TgUser:
|
||||||
|
async with db_session_maker() as db_session, db_session.begin():
|
||||||
|
telegram_user: TgUser | None = await db_session.get(TgUser, user.id)
|
||||||
|
if telegram_user:
|
||||||
|
return telegram_user
|
||||||
|
try:
|
||||||
|
async with db_session_maker() as db_session, db_session.begin():
|
||||||
|
telegram_user = TgUser(
|
||||||
|
id=user.id,
|
||||||
|
username=user.username,
|
||||||
|
first_name=user.first_name,
|
||||||
|
last_name=user.last_name,
|
||||||
|
language_code=user.language_code,
|
||||||
|
is_bot=user.is_bot,
|
||||||
|
is_premium=user.is_premium,
|
||||||
|
added_to_attachment_menu=user.added_to_attachment_menu,
|
||||||
|
)
|
||||||
|
db_session.add(telegram_user)
|
||||||
|
return telegram_user
|
||||||
|
except IntegrityError:
|
||||||
|
telegram_user = await db_session.get(TgUser, user.id)
|
||||||
|
if telegram_user is None:
|
||||||
|
raise Exception(f"Can't find telegram_user = {user.id}") from None
|
||||||
|
return telegram_user
|
||||||
26
src/greek_lang/users/models.py
Normal file
26
src/greek_lang/users/models.py
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from sqlalchemy import BigInteger, Boolean, DateTime, String, func
|
||||||
|
from sqlalchemy.orm import Mapped, mapped_column
|
||||||
|
|
||||||
|
from greek_lang.database.base import Base
|
||||||
|
|
||||||
|
|
||||||
|
class User(Base):
|
||||||
|
__tablename__ = "users"
|
||||||
|
|
||||||
|
id: Mapped[int] = mapped_column(BigInteger, primary_key=True, index=True)
|
||||||
|
is_bot: Mapped[bool] = mapped_column(Boolean, nullable=False)
|
||||||
|
first_name: Mapped[str | None] = mapped_column(String, nullable=True)
|
||||||
|
last_name: Mapped[str | None] = mapped_column(String, nullable=True)
|
||||||
|
username: Mapped[str | None] = mapped_column(String, nullable=True, index=True)
|
||||||
|
language_code: Mapped[str | None] = mapped_column(String(length=8), nullable=True)
|
||||||
|
is_premium: Mapped[bool | None] = mapped_column(Boolean, nullable=True)
|
||||||
|
added_to_attachment_menu: Mapped[bool | None] = mapped_column(
|
||||||
|
Boolean, nullable=True
|
||||||
|
)
|
||||||
|
registered_at: Mapped[datetime] = mapped_column(
|
||||||
|
DateTime(timezone=True),
|
||||||
|
server_default=func.now(),
|
||||||
|
nullable=False,
|
||||||
|
)
|
||||||
@ -6,7 +6,7 @@ import logging
|
|||||||
import logging.config
|
import logging.config
|
||||||
import types
|
import types
|
||||||
|
|
||||||
import cgitb
|
import cgitb # type: ignore[import-untyped]
|
||||||
import telebot
|
import telebot
|
||||||
from requests import ReadTimeout
|
from requests import ReadTimeout
|
||||||
|
|
||||||
|
|||||||
14
uv.lock
14
uv.lock
@ -417,6 +417,7 @@ dev = [
|
|||||||
{ name = "pre-commit" },
|
{ name = "pre-commit" },
|
||||||
{ name = "pyupgrade" },
|
{ name = "pyupgrade" },
|
||||||
{ name = "ruff" },
|
{ name = "ruff" },
|
||||||
|
{ name = "types-requests" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.metadata]
|
[package.metadata]
|
||||||
@ -452,6 +453,7 @@ dev = [
|
|||||||
{ name = "pre-commit", specifier = ">=4.2.0" },
|
{ name = "pre-commit", specifier = ">=4.2.0" },
|
||||||
{ name = "pyupgrade", specifier = ">=3.20.0" },
|
{ name = "pyupgrade", specifier = ">=3.20.0" },
|
||||||
{ name = "ruff", specifier = ">=0.11.13" },
|
{ name = "ruff", specifier = ">=0.11.13" },
|
||||||
|
{ name = "types-requests", specifier = ">=2.32.4.20250809" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1292,6 +1294,18 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl", hash = "sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2", size = 78540, upload-time = "2024-11-24T20:12:19.698Z" },
|
{ url = "https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl", hash = "sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2", size = 78540, upload-time = "2024-11-24T20:12:19.698Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "types-requests"
|
||||||
|
version = "2.32.4.20250809"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "urllib3" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/ed/b0/9355adb86ec84d057fea765e4c49cce592aaf3d5117ce5609a95a7fc3dac/types_requests-2.32.4.20250809.tar.gz", hash = "sha256:d8060de1c8ee599311f56ff58010fb4902f462a1470802cf9f6ed27bc46c4df3", size = 23027, upload-time = "2025-08-09T03:17:10.664Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2b/6f/ec0012be842b1d888d46884ac5558fd62aeae1f0ec4f7a581433d890d4b5/types_requests-2.32.4.20250809-py3-none-any.whl", hash = "sha256:f73d1832fb519ece02c85b1f09d5f0dd3108938e7d47e7f94bbfa18a6782b163", size = 20644, upload-time = "2025-08-09T03:17:09.716Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typing-extensions"
|
name = "typing-extensions"
|
||||||
version = "4.14.1"
|
version = "4.14.1"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user