Files

1108 lines
40 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import asyncio
from aiogram import Bot, types
from aiogram.enums import MessageOriginType, ParseMode
from aiogram.fsm.context import FSMContext
from birthday_pool_bot.dto import (
PaymentData,
Pool,
Subscription,
User,
)
from birthday_pool_bot.repositories.repositories import (
PoolsRepository,
SubscriptionsRepository,
UsersRepository,
)
from . import constants, logic
from .callback_data import (
NotifyNewPoolCallbackData,
PoolCallbackData,
SubscriptionCallbackData,
)
from .exceptions import FlowInternalError
from .states import (
NewSubscriptionPoolState,
NewSubscriptionState,
MenuState,
SetProfileBirthdayState,
SetProfileGiftPaymentDataState,
SetProfileNameState,
SetProfilePhoneState,
)
from .utils import get_telegram_user_full_name, parse_date, parse_phone
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 = parse_phone(text=message.contact.phone_number)
if phone_number is None:
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(text=message.text)
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
phone_number = parse_phone(text=phone_number)
if phone_number is None:
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 new_subscription_message_handler(
message: types.Message,
state: FSMContext,
):
await logic.ask_new_subscription_user(message=message)
await state.set_state(NewSubscriptionState.WAITING_FOR_PHONE)
async def new_subscription_callback_handler(
callback_query: types.CallbackQuery,
state: FSMContext,
):
await logic.ask_new_subscription_user(callback_query=callback_query)
await state.set_state(NewSubscriptionState.WAITING_FOR_PHONE)
async def ask_new_subscription_user_message_handler(
message: types.Message,
state: FSMContext,
):
await logic.ask_new_subscription_user(message=message)
await state.set_state(NewSubscriptionState.WAITING_FOR_PHONE)
async def set_new_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_generator = users_repository.get_users_by_primary_keys(
phone=message.contact.phone_number,
telegram_id=message.contact.user_id,
)
subscription_users = [user async for user in subscription_users_generator]
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_new_subscription_user(message=message)
await state.set_state(NewSubscriptionState.WAITING_FOR_PHONE)
return
if message.forward_origin.type != MessageOriginType.USER:
await message.reply(
text="Это сообщение не от пользователя, попробуйте ещё раз",
)
await logic.ask_new_subscription_user(message=message)
await state.set_state(NewSubscriptionState.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 = parse_phone(text=message.text)
if user_phone is None:
await logic.ask_new_subscription_user(message=message)
await state.set_state(NewSubscriptionState.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_new_subscription_user(message=message)
await state.set_state(NewSubscriptionState.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_new_subscription_user(message=message)
await state.set_state(NewSubscriptionState.WAITING_FOR_PHONE)
return
await state.update_data(
subscription_user_id=str(subscription_user.id),
)
if subscription_user.birthday is None:
await logic.ask_new_subscription_user_birthday(message=message)
await state.set_state(NewSubscriptionState.WAITING_FOR_DATE)
return
await logic.ask_new_subscription_name(
message=message,
users_repository=users_repository,
subscription_user_id=subscription_user.id,
)
await state.set_state(NewSubscriptionState.WAITING_FOR_NAME)
async def ask_new_subscription_user_birthday_message_handler(
message: types.Message,
state: FSMContext,
):
await logic.ask_new_subscription_user_birthday(message=message)
await state.set_state(NewSubscriptionState.WAITING_FOR_DATE)
async def set_new_subscription_user_birthday_message_handler(
message: types.Message,
state: FSMContext,
users_repository: UsersRepository,
):
birthday = parse_date(text=message.text)
if birthday is None:
await logic.ask_new_subscription_user_birthday(message=message)
await state.set_state(NewSubscriptionState.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_new_subscription_user(message=message)
await state.set_state(NewSubscriptionState.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_new_subscription_user(message=message)
await state.set_state(NewSubscriptionState.WAITING_FOR_PHONE)
return
subscription_user.birthday = birthday
await users_repository.update_user(user=subscription_user)
await logic.ask_new_subscription_name(
message=message,
users_repository=users_repository,
subscription_user_id=subscription_user.id,
)
await state.set_state(NewSubscriptionState.WAITING_FOR_NAME)
async def ask_new_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_new_subscription_user(message=message)
await state.set_state(NewSubscriptionState.WAITING_FOR_PHONE)
return
try:
await logic.ask_new_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_new_subscription_user(message=message)
await state.set_state(NewSubscriptionState.WAITING_FOR_PHONE)
return
await state.set_state(NewSubscriptionState.WAITING_FOR_NAME)
async def set_new_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_new_subscription_user(message=message)
await state.set_state(NewSubscriptionState.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_new_subscription_user(message=message)
await state.set_state(NewSubscriptionState.WAITING_FOR_PHONE)
return
await state.update_data(subscription_name=message.text)
await logic.ask_new_subscription_pool_decision(
message=message,
pools_repository=pools_repository,
users_repository=users_repository,
subscription_user_id=subscription_user_id,
)
await state.set_state(NewSubscriptionState.WAITING_FOR_POOL_DECISION)
async def ask_new_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_new_subscription_user(message=message)
await state.set_state(NewSubscriptionState.WAITING_FOR_PHONE)
return
try:
await logic.ask_new_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_new_subscription_user(message=message)
await state.set_state(NewSubscriptionState.WAITING_FOR_PHONE)
return
await state.set_state(NewSubscriptionState.WAITING_FOR_POOL_DECISION)
async def ask_new_subscription_pool_decision_callback_handler(
callback_query: 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 callback_query.answer(text=constants.ERROR_MESSAGE)
await logic.ask_new_subscription_user(message=callback_query.message)
await state.set_state(NewSubscriptionState.WAITING_FOR_PHONE)
return
try:
await logic.ask_new_subscription_pool_decision(
message=callback_query.message,
pools_repository=pools_repository,
users_repository=users_repository,
subscription_user_id=subscription_user_id,
)
except FlowInternalError:
await callback_query.answer(text=constants.ERROR_MESSAGE)
await logic.ask_new_subscription_user(message=callback_query.message)
await state.set_state(NewSubscriptionState.WAITING_FOR_PHONE)
return
await state.set_state(NewSubscriptionState.WAITING_FOR_POOL_DECISION)
async def show_new_subscription_choosing_pools_message_handler(
message: types.Message,
state: FSMContext,
user: User,
users_repository: UsersRepository,
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_new_subscription_user(message=message)
await state.set_state(NewSubscriptionState.WAITING_FOR_PHONE)
return
try:
await logic.show_new_subscription_choosing_pools(
user=user,
users_repository=users_repository,
pools_repository=pools_repository,
subscription_user_id=subscription_user_id,
message=message,
)
except FlowInternalError:
await message.reply(text=constants.ERROR_MESSAGE)
await logic.ask_new_subscription_user(message=message)
await state.set_state(NewSubscriptionState.WAITING_FOR_PHONE)
return
await state.set_state(NewSubscriptionState.WAITING_FOR_CHOOSE_POOL)
async def show_new_subscription_choosing_pools_callback_handler(
callback_query: types.CallbackQuery,
state: FSMContext,
user: User,
users_repository: UsersRepository,
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 callback_query.answer(text=constants.ERROR_MESSAGE)
await logic.ask_new_subscription_user(message=callback_query.message)
await state.set_state(NewSubscriptionState.WAITING_FOR_PHONE)
return
try:
await logic.show_new_subscription_choosing_pools(
user=user,
users_repository=users_repository,
pools_repository=pools_repository,
subscription_user_id=subscription_user_id,
message=callback_query.message,
)
except FlowInternalError:
await callback_query.answer(text=constants.ERROR_MESSAGE)
await logic.ask_new_subscription_user(message=callback_query.message)
await state.set_state(NewSubscriptionState.WAITING_FOR_PHONE)
return
await state.set_state(NewSubscriptionState.WAITING_FOR_CHOOSE_POOL)
async def show_new_subscription_choosing_pool_callback_handler(
callback_query: types.CallbackQuery,
state: FSMContext,
user: User,
users_repository: UsersRepository,
pools_repository: PoolsRepository,
):
callback_data = PoolCallbackData.unpack(callback_query.data)
try:
await logic.show_new_subscription_choosing_pool(
pools_repository=pools_repository,
pool_id=callback_data.id,
callback_query=callback_query,
)
except FlowInternalError:
await callback_query.answer(text=constants.ERROR_MESSAGE)
await logic.show_new_subscription_choosing_pools(
user=user,
users_repository=users_repository,
pools_repository=pools_repository,
subscription_user_id=callback_data.user_id,
)
await state.set_state(NewSubscriptionState.WAITING_FOR_CHOOSE_POOL)
return
await state.set_state(NewSubscriptionState.WAITING_FOR_CHOOSE_POOL)
async def choose_new_subscription_pool_callback_handler(
callback_query: types.CallbackQuery,
state: FSMContext,
user: User,
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")
if not all((subscription_user_id, subscription_name)):
await callback_query.answer(text=constants.ERROR_MESSAGE)
await logic.ask_new_subscription_user(message=callback_query.message)
await state.set_state(NewSubscriptionState.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 callback_query.answer(text=constants.ERROR_MESSAGE)
await logic.ask_new_subscription_user(message=callback_query.message)
await state.set_state(NewSubscriptionState.WAITING_FOR_PHONE)
return
callback_data = PoolCallbackData.unpack(callback_query.data)
async with pools_repository.transaction():
subscription_pool = await pools_repository.get_pool_by_id(
pool_id=callback_data.id,
)
if subscription_pool is None:
await callback_query.answer(text=constants.ERROR_MESSAGE)
await logic.show_new_subscription_choosing_pools(
user=user,
users_repository=users_repository,
pools_repository=pools_repository,
subscription_user_id=subscription_user_id,
callback_query=callback_query,
)
await state.set_state(NewSubscriptionState.WAITING_FOR_CHOOSE_POOL)
return
await state.update_data(
subscription_pool_id=str(callback_data.id),
)
try:
await logic.ask_new_subscription_confirmation(
message=callback_query.message,
users_repository=users_repository,
pools_repository=pools_repository,
subscription_name=subscription_name,
subscription_user_id=subscription_user_id,
subscription_pool_id=callback_data.id,
)
except FlowInternalError:
await callback_query.answer(text=constants.ERROR_MESSAGE)
await logic.show_new_subscription_choosing_pools(
message=callback_query.message,
users_repository=users_repository,
pools_repository=pools_repository,
subscription_name=subscription_name,
subscription_user_id=subscription_user_id,
subscription_pool_id=callback_data.id,
)
await state.set_state(NewSubscriptionState.WAITING_FOR_CHOOSE_POOL)
return
await state.set_state(NewSubscriptionState.WAITING_FOR_CONFIRMATION)
async def ask_new_subscription_pool_description_message_handler(
message: types.Message,
state: FSMContext,
):
await logic.ask_new_subscription_pool_description(message=message)
await state.set_state(NewSubscriptionPoolState.WAITING_FOR_DESCRIPTION)
async def set_new_subscription_pool_description_message_handler(
message: types.Message,
state: FSMContext,
):
description = message.text
await state.update_data(subscription_pool_description=description)
await logic.ask_new_subscription_pool_payment_phone(message=message)
await state.set_state(NewSubscriptionPoolState.WAITING_FOR_PAYMENT_PHONE)
async def ask_new_subscription_pool_payment_phone_message_handler(
message: types.Message,
state: FSMContext,
user: User,
):
await logic.ask_new_subscription_pool_payment_phone(message=message, user=user)
await state.set_state(NewSubscriptionPoolState.WAITING_FOR_PAYMENT_PHONE)
async def set_new_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_new_subscription_pool_payment_phone(message=message)
await state.set_state(NewSubscriptionPoolState.WAITING_FOR_PAYMENT_PHONE)
return
phone_number = parse_phone(text=phone_number)
if phone_number is None:
await message.reply(
text="Некорректный номер телефона, попробуйте ещё раз",
)
await state.set_state(NewSubscriptionPoolState.WAITING_FOR_PAYMENT_PHONE)
return
await state.update_data(subscription_pool_phone=phone_number)
await logic.ask_new_subscription_pool_payment_bank(message=message)
await state.set_state(NewSubscriptionPoolState.WAITING_FOR_PAYMENT_BANK)
async def set_new_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_new_subscription_pool_payment_phone(message=message, user=user)
await state.set_state(NewSubscriptionPoolState.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_new_subscription_user(message=message)
await state.set_state(NewSubscriptionState.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_new_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(NewSubscriptionState.WAITING_FOR_CONFIRMATION)
async def ask_new_subscription_pool_payment_bank_message_handler(
message: types.Message,
state: FSMContext,
):
await logic.ask_new_subscription_pool_payment_bank(message=message)
await state.set_state(NewSubscriptionPoolState.WAITING_FOR_PAYMENT_BANK)
async def set_new_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_new_subscription_user(message=message)
await state.set_state(NewSubscriptionState.WAITING_FOR_PHONE)
return
if subscription_pool_phone is None:
await message.reply(text=constants.ERROR_MESSAGE)
await logic.ask_new_subscription_pool_decision(message=message)
await state.set_state(NewSubscriptionPoolState.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_new_subscription_user(message=message)
await state.set_state(NewSubscriptionState.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_new_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(NewSubscriptionState.WAITING_FOR_CONFIRMATION)
async def ask_new_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_new_subscription_user(message=message)
await state.set_state(NewSubscriptionState.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_new_subscription_user(message=message)
await state.set_state(NewSubscriptionState.WAITING_FOR_PHONE)
return
try:
await logic.ask_new_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_new_subscription_user(message=message)
await state.set_state(NewSubscriptionState.WAITING_FOR_PHONE)
return
await state.set_state(NewSubscriptionState.WAITING_FOR_CONFIRMATION)
async def confirm_new_subscription_callback_handler(
callback_query: types.CallbackQuery,
state: FSMContext,
bot: Bot,
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 callback_query.answer(text=constants.ERROR_MESSAGE)
await logic.ask_new_subscription_user(message=callback_query.message)
await state.set_state(NewSubscriptionState.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 callback_query.answer(text=constants.ERROR_MESSAGE)
await logic.ask_new_subscription_user(message=callback_query.message)
await state.set_state(NewSubscriptionState.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 callback_query.answer(text=constants.ERROR_MESSAGE)
await logic.ask_new_subscription_user(message=callback_query.message)
await state.set_state(NewSubscriptionState.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)
subscriptions_generator = subscriptions_repository.get_to_users_subscriptions(
to_users_ids={subscription_user_id},
have_pool=False,
with_from_user=True,
with_pool=True,
with_pool_owner=True,
)
async with subscriptions_repository.transaction():
coroutines = [
logic.notify_user_about_new_subscription_pool(
subscription=subscription,
user=subscription.from_user,
pool=subscription.pool,
pool_owner=subscription.pool.owner,
bot=bot,
)
async for subscription in subscriptions_generator
]
await asyncio.gather(*coroutines, return_exceptions=True)
async def subscribe_to_new_pool_callback_handler(
callback_query: types.CallbackQuery,
user: User,
subscriptions_repository: SubscriptionsRepository,
pools_repository: PoolsRepository,
):
callback_data = NotifyNewPoolCallbackData.unpack(
callback_query.data,
)
async with subscriptions_repository.transaction():
subscription = await subscriptions_repository.get_subscription(
from_user_id=user.id,
to_user_id=callback_data.user_id,
)
async with pools_repository.transaction():
pool = await pools_repository.get_pool_by_id(
pool_id=callback_data.pool_id,
)
if not all((subscription, pool)):
await callback_query.answer(text=constants.ERROR_MESSAGE)
return
async with subscriptions_repository.transaction():
subscription = await subscriptions_repository.set_pool_for_subscription(
from_user_id=subscription.from_user_id,
to_user_id=subscription.to_user_id,
pool_id=pool.id,
)
if subscription is None:
await callback_query.answer(text=constants.ERROR_MESSAGE)
return
await callback_query.answer(text="Вы присоединились к сбору")
async def hide_new_pool_notification(
callback_query: types.CallbackQuery,
):
await callback_query.message.delete()