Init project

This commit is contained in:
2026-01-15 09:47:43 +03:00
commit 3e515c66ec
59 changed files with 5101 additions and 0 deletions

View File

@@ -0,0 +1,894 @@
import asyncio
import uuid
from aiogram import types, F, Router
from aiogram.enums import MessageOriginType, ParseMode
from aiogram.filters import Command
from aiogram.fsm.context import FSMContext
from aiogram.utils.keyboard import InlineKeyboardBuilder, ReplyKeyboardBuilder
from pydantic_core import PydanticCustomError
from pydantic_filters import PagePagination
from pydantic_extra_types.phone_numbers import PhoneNumber
from birthday_pool_bot.dto import (
BankEnum,
PaymentData,
Pool,
Subscription,
SubscriptionFilter,
User,
)
from birthday_pool_bot.repositories.repositories import (
PoolsRepository,
SubscriptionsRepository,
UsersRepository,
)
from . import constants, logic
from .callback_data import (
AddSubscriptionCallbackData,
AddSubscriptionConfirmCallbackData,
ConfirmAnswerEnum,
MenuCallbackData,
SubscriptionCallbackData,
SubscriptionsCallbackData,
)
from .exceptions import FlowInternalError
from .states import (
AddSubscriptionPoolState,
AddSubscriptionState,
MenuState,
SetProfileBirthdayState,
SetProfileGiftPaymentDataState,
SetProfileNameState,
SetProfilePhoneState,
)
from .utils import get_telegram_user_full_name, parse_date
async def fallback_message_handler(
message: types.Message,
state: FSMContext,
):
await message.reply(text=constants.ERROR_MESSAGE)
await logic.show_menu(message=message)
await state.clear()
await state.set_state(MenuState.MENU)
async def menu_message_handler(
message: types.Message,
state: FSMContext,
):
await logic.show_menu(message=message)
await state.set_state(MenuState.MENU)
async def menu_callback_handler(
callback_query: types.CallbackQuery,
state: FSMContext,
):
await logic.show_menu(message=callback_query.message)
await state.set_state(MenuState.MENU)
async def profile_message_handler(
message: types.Message,
state: FSMContext,
user: User,
):
await logic.show_profile(message=message, user=user)
await state.set_state(MenuState.PROFILE)
async def ask_profile_name_message_handler(
message: types.Message,
state: FSMContext,
):
await logic.ask_profile_name(message=message)
await state.set_state(SetProfileNameState.WAITING_FOR_NAME)
async def set_profile_name_message_handler(
message: types.Message,
state: FSMContext,
user: User,
users_repository: UsersRepository,
):
user.name = message.text
async with users_repository.transaction():
user = await users_repository.update_user(user=user)
await logic.show_profile(message=message, user=user)
await state.set_state(MenuState.PROFILE)
async def ask_profile_phone_message_handler(
message: types.Message,
state: FSMContext,
):
await logic.ask_profile_phone(message=message)
await state.set_state(SetProfilePhoneState.WAITING_FOR_PHONE)
async def set_profile_phone_message_handler(
message: types.Message,
state: FSMContext,
user: User,
users_repository: UsersRepository,
):
if message.contact is None:
await message.reply(
text=(
"Некорректный ответ, пожалуйста, отправьте свой контакт нажатием на кнопку "
"`Поделиться контактом`"
),
parse_mode=ParseMode.MARKDOWN,
)
await logic.ask_profile_phone(message=message)
await state.set_state(SetProfilePhoneState.WAITING_FOR_PHONE)
return
phone_number = message.contact.phone_number
try:
PhoneNumber._validate(phone_number, None)
except PydanticCustomError:
await message.reply(
text="Некорректный номер телефон, попробуйте ещё раз",
)
await state.set_state(SetProfilePhoneState.WAITING_FOR_PHONE)
return
user.phone = phone_number
async with users_repository.transaction():
user = await users_repository.update_user(user=user)
await logic.show_profile(message=message, user=user)
await state.set_state(MenuState.PROFILE)
async def ask_profile_birthdate_message_handler(
message: types.Message,
state: FSMContext,
):
await logic.ask_profile_birthdate(message=message)
await state.set_state(SetProfileBirthdayState.WAITING_FOR_DATE)
async def set_profile_birthdate_message_handler(
message: types.Message,
state: FSMContext,
user: User,
users_repository: UsersRepository,
):
birthday = parse_date(message=message)
if birthday is None:
await logic.ask_profile_birthdate(message=message)
await state.set_state(SetProfileBirthdayState.WAITING_FOR_DATE)
return
user.birthday = birthday
async with users_repository.transaction():
await users_repository.update_user(user=user)
await logic.show_profile(message=message, user=user)
await state.set_state(MenuState.PROFILE)
async def ask_profile_gift_payment_phone_message_handler(
message: types.Message,
state: FSMContext,
):
await logic.ask_profile_gift_payment_phone(message=message)
await state.set_state(SetProfileGiftPaymentDataState.WAITING_FOR_PHONE)
async def set_profile_gift_payment_phone_message_handler(
message: types.Message,
state: FSMContext,
):
phone_number = None
if message.contact is not None:
phone_number = message.contact.phone_number
elif message.text is not None:
phone_number = message.text
else:
await logic.ask_profile_gift_payment_phone(message=message)
await state.set_state(SetProfileGiftPaymentDataState.WAITING_FOR_PHONE)
return
try:
PhoneNumber._validate(phone_number, None)
except PydanticCustomError:
await message.reply(
text="Некорректный номер телефон, попробуйте ещё раз",
)
await state.set_state(SetProfileGiftPaymentDataState.WAITING_FOR_PHONE)
return
await state.update_data(gift_payment_phone=phone_number)
await logic.ask_profile_gift_payment_bank(
message=message,
)
await state.set_state(SetProfileGiftPaymentDataState.WAITING_FOR_BANK)
async def ask_profile_gift_payment_bank_message_handler(
message: types.Message,
state: FSMContext,
):
await logic.ask_profile_gift_payment_bank(message=message)
await state.set_state(SetProfileGiftPaymentDataState.WAITING_FOR_BANK)
async def set_profile_gift_payment_bank_message_handler(
message: types.Message,
state: FSMContext,
user: User,
users_repository: UsersRepository,
):
data = await state.get_data()
if "gift_payment_phone" not in data:
await message.reply(text=constants.ERROR_MESSAGE)
await logic.ask_profile_gift_payment_phone(message=message)
await state.set_state(SetProfileGiftPaymentDataState.WAITING_FOR_PHONE)
return
phone = data["gift_payment_phone"]
bank_name = message.text
if bank_name not in constants.BANKS_MAP:
await message.reply(text="Неизвестный банк, попробуйте ещё раз")
await logic.ask_profile_gift_payment_bank(message=message)
await state.set_state(SetProfileGiftPaymentDataState.WAITING_FOR_BANK)
bank = constants.BANKS_MAP[bank_name]
user.gift_payment_data = PaymentData(
phone=phone,
bank=bank,
)
async with users_repository.transaction():
user = await users_repository.update_user(user=user)
await logic.show_profile(message=message, user=user)
await state.set_state(MenuState.PROFILE)
async def subscriptions_message_handler(
message: types.Message,
state: FSMContext,
user: User,
subscriptions_repository: SubscriptionsRepository,
):
await logic.show_subscriptions(
user=user,
subscriptions_repository=subscriptions_repository,
message=message,
)
await state.set_state(MenuState.SUBSCRIPTIONS)
async def subscriptions_callback_handler(
callback_query: types.CallbackQuery,
state: FSMContext,
user: User,
subscriptions_repository: SubscriptionsRepository,
):
await logic.show_subscriptions(
user=user,
subscriptions_repository=subscriptions_repository,
message=callback_query.message,
)
await state.set_state(MenuState.SUBSCRIPTIONS)
async def subscription_callback_handler(
callback_query: types.CallbackQuery,
state: FSMContext,
user: User,
subscriptions_repository: SubscriptionsRepository,
):
callback_data = SubscriptionCallbackData.unpack(callback_query.data)
await logic.show_subscription(
from_user_id=user.id,
to_user_id=callback_data.to_user_id,
subscriptions_repository=subscriptions_repository,
callback_query=callback_query,
)
await state.set_state(MenuState.SUBSCRIPTIONS)
async def delete_subscription_callback(
callback_query: types.CallbackQuery,
state: FSMContext,
user: User,
subscriptions_repository: SubscriptionsRepository,
):
callback_data = SubscriptionCallbackData.unpack(callback_query.data)
await logic.delete_subscription(
from_user_id=user.id,
to_user_id=callback_data.to_user_id,
subscriptions_repository=subscriptions_repository,
callback_query=callback_query,
)
await logic.show_subscriptions(
user=user,
subscriptions_repository=subscriptions_repository,
message=callback_query.message,
)
await state.set_state(MenuState.SUBSCRIPTIONS)
async def add_subscription_message_handler(
message: types.Message,
state: FSMContext,
):
await logic.ask_add_subscription_user(message=message)
await state.set_state(AddSubscriptionState.WAITING_FOR_PHONE)
async def add_subscription_callback_handler(
callback_query: types.CallbackQuery,
state: FSMContext,
):
await logic.ask_add_subscription_user(callback_query=callback_query)
await state.set_state(AddSubscriptionState.WAITING_FOR_PHONE)
async def ask_add_subscription_user_message_handler(
message: types.Message,
state: FSMContext,
):
await logic.ask_add_subscription_user(message=message)
await state.set_state(AddSubscriptionState.WAITING_FOR_PHONE)
async def set_add_subscription_user_message_handler(
message: types.Message,
state: FSMContext,
user: User,
users_repository: UsersRepository,
subscriptions_repository: SubscriptionsRepository,
):
user_name, user_phone, user_telegram_id = None, None, None
async with users_repository.transaction():
if message.contact is not None:
subscription_users = await users_repository.get_users_by_primary_keys(
phone=message.contact.phone_number,
telegram_id=message.contact.user_id,
)
subscription_user = await users_repository.merge_users(*subscription_users)
user_name = get_telegram_user_full_name(message.contact)
user_phone = message.contact.phone_number
user_telegram_id = message.contact.user_id
elif message.forward_origin is not None:
if message.forward_origin.type == MessageOriginType.HIDDEN_USER:
await message.reply(
text="Пользователь скрыл свои данные, попробуйте отправить номер телефона или его контакт",
)
await logic.ask_add_subscription_user(message=message)
await state.set_state(AddSubscriptionState.WAITING_FOR_PHONE)
return
if message.forward_origin.type != MessageOriginType.USER:
await message.reply(
text="Это сообщение не от пользователя, попробуйте ещё раз",
)
await logic.ask_add_subscription_user(message=message)
await state.set_state(AddSubscriptionState.WAITING_FOR_PHONE)
return
user_name = get_telegram_user_full_name(message.forward_origin.sender_user)
user_telegram_id = message.forward_origin.sender_user.id
subscription_user = await users_repository.get_user_by_telegram_id(
telegram_id=user_telegram_id,
)
elif message.text:
user_phone = message.text
try:
PhoneNumber._validate(user_phone, None)
except PydanticCustomError:
await logic.ask_add_subscription_user(message=message)
await state.set_state(AddSubscriptionState.WAITING_FOR_PHONE)
return
subscription_user = await users_repository.get_user_by_phone(phone=user_phone)
if subscription_user is None:
subscription_user = User(
name=user_name,
phone=user_phone,
telegram_id=user_telegram_id,
)
async with users_repository.transaction():
subscription_user = await users_repository.create_user(user=subscription_user)
if subscription_user.id == user.id:
await message.reply("Нельзя подписаться на самого себя")
await logic.ask_add_subscription_user(message=message)
await state.set_state(AddSubscriptionState.WAITING_FOR_PHONE)
return
async with subscriptions_repository.transaction():
subscription = await subscriptions_repository.get_subscription(
from_user_id=user.id,
to_user_id=subscription_user.id,
)
if subscription is not None:
await message.reply(text="У вас уже есть подписка на этого человека")
await logic.ask_add_subscription_user(message=message)
await state.set_state(AddSubscriptionState.WAITING_FOR_PHONE)
return
await state.update_data(
subscription_user_id=subscription_user.id,
)
if subscription_user.birthday is None:
await logic.ask_add_subscription_user_birthday(message=message)
await state.set_state(AddSubscriptionState.WAITING_FOR_DATE)
return
await logic.ask_add_subscription_name(
message=message,
users_repository=users_repository,
subscription_user_id=subscription_user.id,
)
await state.set_state(AddSubscriptionState.WAITING_FOR_NAME)
async def ask_add_subscription_user_birthday_message_handler(
message: types.Message,
state: FSMContext,
):
await logic.ask_add_subscription_user_birthday(message=message)
await state.set_state(AddSubscriptionState.WAITING_FOR_DATE)
async def set_add_subscription_user_birthday_message_handler(
message: types.Message,
state: FSMContext,
users_repository: UsersRepository,
):
birthday = parse_date(message=message)
if birthday is None:
await logic.ask_add_subscription_user_birthday(message=message)
await state.set_state(AddSubscriptionState.WAITING_FOR_DATE)
return
state_data = await state.get_data()
subscription_user_id = state_data.get("subscription_user_id")
if subscription_user_id is None:
await message.reply(text=constants.ERROR_MESSAGE)
await logic.ask_add_subscription_user(message=message)
await state.set_state(AddSubscriptionState.WAITING_FOR_PHONE)
return
async with users_repository.transaction():
subscription_user = await users_repository.get_user_by_id(user_id=subscription_user_id)
if subscription_user is None:
await message.reply(text=constants.ERROR_MESSAGE)
await logic.ask_add_subscription_user(message=message)
await state.set_state(AddSubscriptionState.WAITING_FOR_PHONE)
return
subscription_user.birthday = birthday
await users_repository.update_user(user=subscription_user)
await logic.ask_add_subscription_name(
message=message,
users_repository=users_repository,
subscription_user_id=subscription_user.id,
)
await state.set_state(AddSubscriptionState.WAITING_FOR_NAME)
async def ask_add_subscription_name_message_handler(
message: types.Message,
state: FSMContext,
users_repository: UsersRepository,
):
state_data = await state.get_data()
subscription_user_id = state_data.get("subscription_user_id")
if subscription_user_id is None:
await message.reply(text=constants.ERROR_MESSAGE)
await logic.ask_add_subscription_user(message=message)
await state.set_state(AddSubscriptionState.WAITING_FOR_PHONE)
return
try:
await logic.ask_add_subscription_name(
message=message,
users_repository=users_repository,
subscription_user_id=subscription_user_id,
)
except FlowInternalError:
await message.reply(text=constants.ERROR_MESSAGE)
await logic.ask_add_subscription_user(message=message)
await state.set_state(AddSubscriptionState.WAITING_FOR_PHONE)
return
await state.set_state(AddSubscriptionState.WAITING_FOR_NAME)
async def set_add_subscription_name_message_handler(
message: types.Message,
state: FSMContext,
user: User,
pools_repository: PoolsRepository,
subscriptions_repository: SubscriptionsRepository,
users_repository: UsersRepository,
):
state_data = await state.get_data()
subscription_user_id = state_data.get("subscription_user_id")
if subscription_user_id is None:
await message.reply(text=constants.ERROR_MESSAGE)
await logic.ask_add_subscription_user(message=message)
await state.set_state(AddSubscriptionState.WAITING_FOR_PHONE)
return
async with users_repository.transaction():
subscription_user = await users_repository.get_user_by_id(user_id=subscription_user_id)
if subscription_user is None or subscription_user.birthday is None:
await message.reply(text=constants.ERROR_MESSAGE)
await logic.ask_add_subscription_user(message=message)
await state.set_state(AddSubscriptionState.WAITING_FOR_PHONE)
return
await state.update_data(subscription_name=message.text)
await logic.ask_add_subscription_pool_decision(
message=message,
pools_repository=pools_repository,
users_repository=users_repository,
subscription_user_id=subscription_user_id,
)
await state.set_state(AddSubscriptionState.WAITING_FOR_POOL_DECISION)
async def ask_add_subscription_pool_decision_message_handler(
message: types.Message,
state: FSMContext,
pools_repository: PoolsRepository,
users_repository: UsersRepository,
):
state_data = await state.get_data()
subscription_user_id = state_data.get("subscription_user_id")
if subscription_user_id is None:
await message.reply(text=constants.ERROR_MESSAGE)
await logic.ask_add_subscription_user(message=message)
await state.set_state(AddSubscriptionState.WAITING_FOR_PHONE)
return
try:
await logic.ask_add_subscription_pool_decision(
message=message,
pools_repository=pools_repository,
users_repository=users_repository,
subscription_user_id=subscription_user_id,
)
except FlowInternalError:
await message.reply(text=constants.ERROR_MESSAGE)
await logic.ask_add_subscription_user(message=message)
await state.set_state(AddSubscriptionState.WAITING_FOR_PHONE)
return
await state.set_state(AddSubscriptionState.WAITING_FOR_POOL_DECISION)
async def show_add_subscription_pools_message_handler(
message: types.Message,
state: FSMContext,
user: User,
pools_repository: PoolsRepository,
):
state_data = await state.get_data()
subscription_user_id = state_data.get("subscription_user_id")
if subscription_user_id is None:
await message.reply(text=constants.ERROR_MESSAGE)
await logic.ask_add_subscription_user(message=message)
await state.set_state(AddSubscriptionState.WAITING_FOR_PHONE)
return
try:
await logic.show_add_subscription_pools(
user=user,
pools_repository=pools_repository,
message=message,
)
except FlowInternalError:
await message.reply(text=constants.ERROR_MESSAGE)
await logic.ask_add_subscription_user(message=message)
await state.set_state(AddSubscriptionState.WAITING_FOR_PHONE)
return
await logic.ask_add_subscription_pool_description(message=message)
await state.set_state(AddSubscriptionPoolState.WAITING_FOR_DESCRIPTION)
async def ask_add_subscription_pool_description_message_handler(
message: types.Message,
state: FSMContext,
):
await logic.ask_add_subscription_pool_description(message=message)
await state.set_state(AddSubscriptionPoolState.WAITING_FOR_DESCRIPTION)
async def set_add_subscription_pool_description_message_handler(
message: types.Message,
state: FSMContext,
):
description = message.text
await state.update_data(subscription_pool_description=description)
await logic.ask_add_subscription_pool_payment_phone(message=message)
await state.set_state(AddSubscriptionPoolState.WAITING_FOR_PAYMENT_PHONE)
async def ask_add_subscription_pool_payment_phone_message_handler(
message: types.Message,
state: FSMContext,
user: User,
):
await logic.ask_add_subscription_pool_payment_phone(message=message, user=user)
await state.set_state(AddSubscriptionPoolState.WAITING_FOR_PAYMENT_PHONE)
async def set_add_subscription_pool_payment_phone_message_handler(
message: types.Message,
state: FSMContext,
):
phone_number = None
if message.contact is not None:
phone_number = message.contact.phone_number
elif message.text is not None:
phone_number = message.text
else:
await message.reply(text="Некорректный номер телефона, попробуйте ещё раз")
await logic.ask_add_subscription_pool_payment_phone(message=message)
await state.set_state(AddSubscriptionPoolState.WAITING_FOR_PAYMENT_PHONE)
return
try:
PhoneNumber._validate(phone_number, None)
except PydanticCustomError:
await message.reply(
text="Некорректный номер телефона, попробуйте ещё раз",
)
await state.set_state(AddSubscriptionPoolState.WAITING_FOR_PAYMENT_PHONE)
return
await state.update_data(subscription_pool_phone=phone_number)
await logic.ask_add_subscription_pool_payment_bank(message=message)
await state.set_state(AddSubscriptionPoolState.WAITING_FOR_PAYMENT_BANK)
async def set_add_subscription_pool_payment_data_from_profile_message_handler(
message: types.Message,
state: FSMContext,
user: User,
users_repository: UsersRepository,
pools_repository: PoolsRepository,
):
if user.gift_payment_data is None:
await message.reply(text=constants.ERROR_MESSAGE)
await logic.ask_add_subscription_pool_payment_phone(message=message, user=user)
await state.set_state(AddSubscriptionPoolState.WAITING_FOR_PAYMENT_PHONE)
return
state_data = await state.get_data()
subscription_user_id = state_data.get("subscription_user_id")
subscription_name = state_data.get("subscription_name")
subscription_pool_description = state_data.get("subscription_pool_description")
if not all((subscription_user_id, subscription_name)):
await message.reply(text=constants.ERROR_MESSAGE)
await logic.ask_add_subscription_user(message=message)
await state.set_state(AddSubscriptionState.WAITING_FOR_PHONE)
return
await state.update_data(
subscription_pool_phone=user.gift_payment_data.phone,
subscription_pool_bank=user.gift_payment_data.bank,
)
await logic.ask_add_subscription_confirmation(
message=message,
users_repository=users_repository,
pools_repository=pools_repository,
subscription_name=subscription_name,
subscription_user_id=subscription_user_id,
subscription_pool_description=subscription_pool_description,
subscription_pool_phone=user.gift_payment_data.phone,
subscription_pool_bank=user.gift_payment_data.bank,
)
await state.set_state(AddSubscriptionState.WAITING_FOR_CONFIRMATION)
async def ask_add_subscription_pool_payment_bank_message_handler(
message: types.Message,
state: FSMContext,
):
await logic.ask_add_subscription_pool_payment_bank(message=message)
await state.set_state(AddSubscriptionPoolState.WAITING_FOR_PAYMENT_BANK)
async def set_add_subscription_pool_payment_bank_message_handler(
message: types.Message,
state: FSMContext,
users_repository: UsersRepository,
pools_repository: PoolsRepository,
):
state_data = await state.get_data()
subscription_user_id = state_data.get("subscription_user_id")
subscription_name = state_data.get("subscription_name")
subscription_pool_description = state_data.get("subscription_pool_description")
subscription_pool_phone = state_data.get("subscription_pool_phone")
if not all((subscription_user_id, subscription_name)):
await message.reply(text=constants.ERROR_MESSAGE)
await logic.ask_add_subscription_user(message=message)
await state.set_state(AddSubscriptionState.WAITING_FOR_PHONE)
return
if subscription_pool_phone is None:
await message.reply(text=constants.ERROR_MESSAGE)
await logic.ask_add_subscription_pool_decision(message=message)
await state.set_state(AddSubscriptionPoolState.WAITING_FOR_DESCRIPTION)
return
async with users_repository.transaction():
subscription_user = await users_repository.get_user_by_id(
user_id=subscription_user_id,
)
if subscription_user is None:
await message.reply(text=constants.ERROR_MESSAGE)
await logic.ask_add_subscription_user(message=message)
await state.set_state(AddSubscriptionState.WAITING_FOR_PHONE)
return
bank_name = message.text
if bank_name not in constants.BANKS_MAP:
await message.reply(text="Неизвестный банк, попробуйте ещё раз")
await logic.ask_profile_gift_payment_bank(message=message)
await state.set_state(SetProfileGiftPaymentDataState.WAITING_FOR_BANK)
bank = constants.BANKS_MAP[bank_name]
await state.update_data(subscription_pool_bank=bank)
await logic.ask_add_subscription_confirmation(
message=message,
users_repository=users_repository,
pools_repository=pools_repository,
subscription_name=subscription_name,
subscription_user_id=subscription_user_id,
subscription_pool_description=subscription_pool_description,
subscription_pool_phone=subscription_pool_phone,
subscription_pool_bank=bank,
)
await state.set_state(AddSubscriptionState.WAITING_FOR_CONFIRMATION)
async def ask_add_subscription_confirmation_message_handler(
message: types.Message,
state: FSMContext,
users_repository: UsersRepository,
pools_repository: PoolsRepository,
):
state_data = await state.get_data()
subscription_user_id = state_data.get("subscription_user_id")
subscription_name = state_data.get("subscription_name")
subscription_pool_id = state_data.get("subscription_pool_id")
subscription_pool_description = state_data.get("subscription_pool_description")
subscription_pool_phone = state_data.get("subscription_pool_phone")
subscription_pool_bank = state_data.get("subscription_pool_bank")
if not all((subscription_user_id, subscription_name)):
await message.reply(text=constants.ERROR_MESSAGE)
await logic.ask_add_subscription_user(message=message)
await state.set_state(AddSubscriptionState.WAITING_FOR_PHONE)
return
async with users_repository.transaction():
subscription_user = await users_repository.get_user_by_id(
user_id=subscription_user_id,
)
if subscription_user is None:
await message.reply(text=constants.ERROR_MESSAGE)
await logic.ask_add_subscription_user(message=message)
await state.set_state(AddSubscriptionState.WAITING_FOR_PHONE)
return
try:
await logic.ask_add_subscription_confirmation(
message=message,
users_repository=users_repository,
pools_repository=pools_repository,
subscription_name=subscription_name,
subscription_user_id=subscription_user_id,
subscription_pool_id=subscription_pool_id,
subscription_pool_description=subscription_pool_description,
subscription_pool_phone=subscription_pool_phone,
subscription_pool_bank=subscription_pool_bank,
)
except FlowInternalError:
await message.reply(text=constants.ERROR_MESSAGE)
await logic.ask_add_subscription_user(message=message)
await state.set_state(AddSubscriptionState.WAITING_FOR_PHONE)
return
await state.set_state(AddSubscriptionState.WAITING_FOR_CONFIRMATION)
async def confirm_add_subscription_callback_handler(
callback_query: types.CallbackQuery,
state: FSMContext,
user: User,
pools_repository: PoolsRepository,
subscriptions_repository: SubscriptionsRepository,
users_repository: UsersRepository,
):
state_data = await state.get_data()
subscription_user_id = state_data.get("subscription_user_id")
subscription_name = state_data.get("subscription_name")
subscription_pool_id = state_data.get("subscription_pool_id")
subscription_pool_description = state_data.get("subscription_pool_description")
subscription_pool_phone = state_data.get("subscription_pool_phone")
subscription_pool_bank = state_data.get("subscription_pool_bank")
if not all((subscription_user_id, subscription_name)):
await message.reply(text=constants.ERROR_MESSAGE)
await logic.ask_add_subscription_user(message=message)
await state.set_state(AddSubscriptionState.WAITING_FOR_PHONE)
return
async with users_repository.transaction():
subscription_user = await users_repository.get_user_by_id(
user_id=subscription_user_id,
)
if subscription_user is None:
await message.reply(text=constants.ERROR_MESSAGE)
await logic.ask_add_subscription_user(message=message)
await state.set_state(AddSubscriptionState.WAITING_FOR_PHONE)
return
subscription_pool = None
if subscription_pool_id is not None:
async with pools_repository.transaction():
subscription_pool = await pools_repository.get_pool_by_id(
pool_id=subscription_pool_id,
)
if subscription_pool is None:
await message.reply(text=constants.ERROR_MESSAGE)
await logic.ask_add_subscription_user(message=message)
await state.set_state(AddSubscriptionState.WAITING_FOR_PHONE)
return
if subscription_pool is None and all((subscription_pool_phone, subscription_pool_bank)):
subscription_pool = Pool(
owner_id=user.id,
birthday_user_id=subscription_user.id,
description=subscription_pool_description,
payment_data=PaymentData(
phone=subscription_pool_phone,
bank=subscription_pool_bank,
),
)
async with pools_repository.transaction():
subscription_pool = await pools_repository.create_pool(pool=subscription_pool)
subscription_pool_id = subscription_pool.id
subscription = Subscription(
from_user_id=user.id,
to_user_id=subscription_user_id,
name=subscription_name,
pool_id=subscription_pool_id,
)
async with subscriptions_repository.transaction():
await subscriptions_repository.create_subscription(
subscription=subscription,
)
await logic.show_subscriptions(
user=user,
subscriptions_repository=subscriptions_repository,
message=callback_query.message,
)
await state.clear()
await state.set_state(MenuState.SUBSCRIPTIONS)