integrate dialog management with initial "main menu" state and update SRS schema
This commit is contained in:
parent
54155a99c5
commit
40ed52777e
@ -5,6 +5,7 @@ Revises: 747797032526
|
|||||||
Create Date: 2025-08-16 19:40:06.376743
|
Create Date: 2025-08-16 19:40:06.376743
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Sequence, Union
|
from typing import Sequence, Union
|
||||||
|
|
||||||
from alembic import op
|
from alembic import op
|
||||||
@ -12,8 +13,8 @@ import sqlalchemy as sa
|
|||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision: str = '9a2898513cf2'
|
revision: str = "9a2898513cf2"
|
||||||
down_revision: Union[str, None] = '747797032526'
|
down_revision: Union[str, None] = "747797032526"
|
||||||
branch_labels: Union[str, Sequence[str], None] = None
|
branch_labels: Union[str, Sequence[str], None] = None
|
||||||
depends_on: Union[str, Sequence[str], None] = None
|
depends_on: Union[str, Sequence[str], None] = None
|
||||||
|
|
||||||
@ -21,51 +22,91 @@ depends_on: Union[str, Sequence[str], None] = None
|
|||||||
def upgrade() -> None:
|
def upgrade() -> None:
|
||||||
"""Upgrade schema."""
|
"""Upgrade schema."""
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.create_table('srs_progress',
|
op.create_table(
|
||||||
sa.Column('id', sa.BigInteger(), nullable=False),
|
"srs_progress",
|
||||||
sa.Column('user_id', sa.BigInteger(), nullable=False),
|
sa.Column("id", sa.BigInteger(), nullable=False),
|
||||||
sa.Column('word_id', sa.BigInteger(), nullable=False),
|
sa.Column("user_id", sa.BigInteger(), nullable=False),
|
||||||
sa.Column('due_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
sa.Column("word_id", sa.BigInteger(), nullable=False),
|
||||||
sa.Column('interval_days', sa.Integer(), nullable=False),
|
sa.Column(
|
||||||
sa.Column('ease', sa.Float(), nullable=False),
|
"due_at",
|
||||||
sa.Column('reps', sa.Integer(), nullable=False),
|
sa.DateTime(timezone=True),
|
||||||
sa.Column('lrn_step', sa.Integer(), nullable=False),
|
server_default=sa.text("now()"),
|
||||||
sa.Column('state', sa.Enum('learning', 'review', 'lapsed', name='reviewstate', native_enum=False), nullable=False),
|
nullable=False,
|
||||||
sa.ForeignKeyConstraint(['user_id'], ['users.id'], name=op.f('fk_srs_progress_user_id_users')),
|
),
|
||||||
sa.ForeignKeyConstraint(['word_id'], ['glossary_word.id'], name=op.f('fk_srs_progress_word_id_glossary_word')),
|
sa.Column("interval_days", sa.Integer(), nullable=False),
|
||||||
sa.PrimaryKeyConstraint('id', name=op.f('pk_srs_progress')),
|
sa.Column("ease", sa.Float(), nullable=False),
|
||||||
sa.UniqueConstraint('user_id', 'word_id', name='uq_srs_user_word')
|
sa.Column("reps", sa.Integer(), nullable=False),
|
||||||
|
sa.Column("lrn_step", sa.Integer(), nullable=False),
|
||||||
|
sa.Column(
|
||||||
|
"state",
|
||||||
|
sa.Enum(
|
||||||
|
"learning", "review", "lapsed", name="reviewstate", native_enum=False
|
||||||
|
),
|
||||||
|
nullable=False,
|
||||||
|
),
|
||||||
|
sa.ForeignKeyConstraint(
|
||||||
|
["user_id"], ["users.id"], name=op.f("fk_srs_progress_user_id_users")
|
||||||
|
),
|
||||||
|
sa.ForeignKeyConstraint(
|
||||||
|
["word_id"],
|
||||||
|
["glossary_word.id"],
|
||||||
|
name=op.f("fk_srs_progress_word_id_glossary_word"),
|
||||||
|
),
|
||||||
|
sa.PrimaryKeyConstraint("id", name=op.f("pk_srs_progress")),
|
||||||
|
sa.UniqueConstraint("user_id", "word_id", name="uq_srs_user_word"),
|
||||||
)
|
)
|
||||||
op.create_index(op.f('ix_srs_progress_due_at'), 'srs_progress', ['due_at'], unique=False)
|
op.create_index(
|
||||||
op.create_index(op.f('ix_srs_progress_user_id'), 'srs_progress', ['user_id'], unique=False)
|
op.f("ix_srs_progress_due_at"), "srs_progress", ["due_at"], unique=False
|
||||||
op.create_index(op.f('ix_srs_progress_word_id'), 'srs_progress', ['word_id'], unique=False)
|
)
|
||||||
op.create_table('srs_review_log',
|
op.create_index(
|
||||||
sa.Column('id', sa.BigInteger(), nullable=False),
|
op.f("ix_srs_progress_user_id"), "srs_progress", ["user_id"], unique=False
|
||||||
sa.Column('user_id', sa.BigInteger(), nullable=False),
|
)
|
||||||
sa.Column('word_id', sa.BigInteger(), nullable=False),
|
op.create_index(
|
||||||
sa.Column('ts', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
op.f("ix_srs_progress_word_id"), "srs_progress", ["word_id"], unique=False
|
||||||
sa.Column('grade', sa.Integer(), nullable=False),
|
)
|
||||||
sa.Column('prev_interval', sa.Integer(), nullable=False),
|
op.create_table(
|
||||||
sa.Column('new_interval', sa.Integer(), nullable=False),
|
"srs_review_log",
|
||||||
sa.Column('prev_ease', sa.Float(), nullable=False),
|
sa.Column("id", sa.BigInteger(), nullable=False),
|
||||||
sa.Column('new_ease', sa.Float(), nullable=False),
|
sa.Column("user_id", sa.BigInteger(), nullable=False),
|
||||||
sa.ForeignKeyConstraint(['user_id'], ['users.id'], name=op.f('fk_srs_review_log_user_id_users')),
|
sa.Column("word_id", sa.BigInteger(), nullable=False),
|
||||||
sa.ForeignKeyConstraint(['word_id'], ['glossary_word.id'], name=op.f('fk_srs_review_log_word_id_glossary_word')),
|
sa.Column(
|
||||||
sa.PrimaryKeyConstraint('id', name=op.f('pk_srs_review_log'))
|
"ts",
|
||||||
|
sa.DateTime(timezone=True),
|
||||||
|
server_default=sa.text("now()"),
|
||||||
|
nullable=False,
|
||||||
|
),
|
||||||
|
sa.Column("grade", sa.Integer(), nullable=False),
|
||||||
|
sa.Column("prev_interval", sa.Integer(), nullable=False),
|
||||||
|
sa.Column("new_interval", sa.Integer(), nullable=False),
|
||||||
|
sa.Column("prev_ease", sa.Float(), nullable=False),
|
||||||
|
sa.Column("new_ease", sa.Float(), nullable=False),
|
||||||
|
sa.ForeignKeyConstraint(
|
||||||
|
["user_id"], ["users.id"], name=op.f("fk_srs_review_log_user_id_users")
|
||||||
|
),
|
||||||
|
sa.ForeignKeyConstraint(
|
||||||
|
["word_id"],
|
||||||
|
["glossary_word.id"],
|
||||||
|
name=op.f("fk_srs_review_log_word_id_glossary_word"),
|
||||||
|
),
|
||||||
|
sa.PrimaryKeyConstraint("id", name=op.f("pk_srs_review_log")),
|
||||||
|
)
|
||||||
|
op.create_index(
|
||||||
|
op.f("ix_srs_review_log_user_id"), "srs_review_log", ["user_id"], unique=False
|
||||||
|
)
|
||||||
|
op.create_index(
|
||||||
|
op.f("ix_srs_review_log_word_id"), "srs_review_log", ["word_id"], unique=False
|
||||||
)
|
)
|
||||||
op.create_index(op.f('ix_srs_review_log_user_id'), 'srs_review_log', ['user_id'], unique=False)
|
|
||||||
op.create_index(op.f('ix_srs_review_log_word_id'), 'srs_review_log', ['word_id'], unique=False)
|
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
def downgrade() -> None:
|
def downgrade() -> None:
|
||||||
"""Downgrade schema."""
|
"""Downgrade schema."""
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.drop_index(op.f('ix_srs_review_log_word_id'), table_name='srs_review_log')
|
op.drop_index(op.f("ix_srs_review_log_word_id"), table_name="srs_review_log")
|
||||||
op.drop_index(op.f('ix_srs_review_log_user_id'), table_name='srs_review_log')
|
op.drop_index(op.f("ix_srs_review_log_user_id"), table_name="srs_review_log")
|
||||||
op.drop_table('srs_review_log')
|
op.drop_table("srs_review_log")
|
||||||
op.drop_index(op.f('ix_srs_progress_word_id'), table_name='srs_progress')
|
op.drop_index(op.f("ix_srs_progress_word_id"), table_name="srs_progress")
|
||||||
op.drop_index(op.f('ix_srs_progress_user_id'), table_name='srs_progress')
|
op.drop_index(op.f("ix_srs_progress_user_id"), table_name="srs_progress")
|
||||||
op.drop_index(op.f('ix_srs_progress_due_at'), table_name='srs_progress')
|
op.drop_index(op.f("ix_srs_progress_due_at"), table_name="srs_progress")
|
||||||
op.drop_table('srs_progress')
|
op.drop_table("srs_progress")
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
|||||||
@ -3,6 +3,7 @@ from aiogram import Bot, Dispatcher, BaseMiddleware
|
|||||||
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
|
from aiogram.types import BotCommandScopeAllPrivateChats
|
||||||
|
from aiogram_dialog import 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
|
||||||
@ -24,6 +25,7 @@ def create_bot(
|
|||||||
|
|
||||||
async def create_dispatcher() -> Dispatcher:
|
async def create_dispatcher() -> Dispatcher:
|
||||||
from .router import router as root_router
|
from .router import router as root_router
|
||||||
|
from .dialogs import dialog
|
||||||
|
|
||||||
fsm_storage = await create_fsm_storage()
|
fsm_storage = await create_fsm_storage()
|
||||||
|
|
||||||
@ -35,7 +37,10 @@ async def create_dispatcher() -> Dispatcher:
|
|||||||
for middleware in middlewares:
|
for middleware in middlewares:
|
||||||
dp.update.middleware(middleware)
|
dp.update.middleware(middleware)
|
||||||
|
|
||||||
dp.include_routers(root_router)
|
dp.include_routers(dialog, root_router)
|
||||||
|
|
||||||
|
setup_dialogs(dp)
|
||||||
|
|
||||||
return dp
|
return dp
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,9 @@
|
|||||||
from gettext import gettext
|
|
||||||
|
|
||||||
from aiogram import Router
|
from aiogram import Router
|
||||||
from aiogram.enums import ParseMode
|
|
||||||
from aiogram.filters import CommandStart
|
from aiogram.filters import CommandStart
|
||||||
from aiogram.types import Message
|
from aiogram.types import Message
|
||||||
|
from aiogram_dialog import DialogManager, StartMode
|
||||||
|
|
||||||
|
from greek_lang.tg_bot.dialogs.states import States
|
||||||
from greek_lang.users.manager import get_or_create_telegram_user
|
from greek_lang.users.manager import get_or_create_telegram_user
|
||||||
|
|
||||||
|
|
||||||
@ -12,12 +11,9 @@ router = Router()
|
|||||||
|
|
||||||
|
|
||||||
@router.message(CommandStart())
|
@router.message(CommandStart())
|
||||||
async def start(message: Message) -> None:
|
async def start(message: Message, dialog_manager: DialogManager) -> None:
|
||||||
user = message.from_user
|
user = message.from_user
|
||||||
if user is None:
|
if user is None:
|
||||||
return
|
return
|
||||||
await get_or_create_telegram_user(user)
|
await get_or_create_telegram_user(user)
|
||||||
await message.answer(
|
await dialog_manager.start(States.main_menu, mode=StartMode.RESET_STACK)
|
||||||
text=gettext("Регистрация прошла.").format(user=user.full_name),
|
|
||||||
parse_mode=ParseMode.HTML,
|
|
||||||
)
|
|
||||||
|
|||||||
8
src/greek_lang/tg_bot/dialogs/__init__.py
Normal file
8
src/greek_lang/tg_bot/dialogs/__init__.py
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
from aiogram_dialog import Dialog
|
||||||
|
|
||||||
|
from .main_menu import windows as main_windows
|
||||||
|
|
||||||
|
|
||||||
|
dialog = Dialog(
|
||||||
|
main_windows.main_window,
|
||||||
|
)
|
||||||
0
src/greek_lang/tg_bot/dialogs/main_menu/__init__.py
Normal file
0
src/greek_lang/tg_bot/dialogs/main_menu/__init__.py
Normal file
0
src/greek_lang/tg_bot/dialogs/main_menu/handlers.py
Normal file
0
src/greek_lang/tg_bot/dialogs/main_menu/handlers.py
Normal file
23
src/greek_lang/tg_bot/dialogs/main_menu/windows.py
Normal file
23
src/greek_lang/tg_bot/dialogs/main_menu/windows.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from aiogram.enums import ParseMode
|
||||||
|
from aiogram_dialog import DialogManager, Window
|
||||||
|
from aiogram_dialog.widgets.text import Format
|
||||||
|
|
||||||
|
from ..states import States
|
||||||
|
|
||||||
|
|
||||||
|
async def main_getter(dialog_manager: DialogManager, **kwargs: Any) -> dict[str, Any]:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
|
||||||
|
main_window = Window(
|
||||||
|
Format(
|
||||||
|
"Выбери действие:",
|
||||||
|
when=lambda data, widget, dialog_manager: data["dialog_data"].get("action")
|
||||||
|
is None,
|
||||||
|
),
|
||||||
|
state=States.main_menu,
|
||||||
|
getter=main_getter,
|
||||||
|
parse_mode=ParseMode.HTML,
|
||||||
|
)
|
||||||
5
src/greek_lang/tg_bot/dialogs/states.py
Normal file
5
src/greek_lang/tg_bot/dialogs/states.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
from aiogram.fsm.state import State, StatesGroup
|
||||||
|
|
||||||
|
|
||||||
|
class States(StatesGroup):
|
||||||
|
main_menu = State()
|
||||||
Loading…
Reference in New Issue
Block a user