Files
Travel-Agent/app/callbacks/profile.py
T

279 lines
7.9 KiB
Python

__all__ = ("router",)
from aiogram import F, Router
from aiogram.exceptions import TelegramBadRequest
from aiogram.filters import StateFilter
from aiogram.fsm.context import FSMContext
from aiogram.types import CallbackQuery, Message, ReplyKeyboardRemove
from app import messages, session
from app.filters.user import Registered, RegisteredCallback
from app.keyboards.builders import sex_keyboard
from app.keyboards.profile import get
from app.models.user import User
from app.states.user import UserAlteringState
from app.utils.states import (
delete_message_from_state,
handle_validation_error,
)
router = Router(name="profile_callback")
@router.callback_query(
F.data.startswith("profile_change"),
StateFilter(None),
RegisteredCallback(),
)
async def profile_change_callback(
callback: CallbackQuery,
state: FSMContext,
) -> None:
if (
callback.data is None
or callback.message is None
or not isinstance(callback.message, Message)
):
return
column = callback.data.replace("profile_change_", "")
if column == "username":
message = await callback.message.answer(
f"{messages.EDIT_USERNAME}\n{messages.CANCEL_CHANGE}",
)
elif column == "age":
message = await callback.message.answer(
f"{messages.INPUT_AGE}\n{messages.CANCEL_CHANGE}",
)
elif column == "bio":
message = await callback.message.answer(
f"{messages.EDIT_BIO}\n{messages.CANCEL_CHANGE}",
)
elif column == "sex":
message = await callback.message.answer(
f"{messages.INPUT_SEX}\n{messages.CANCEL_CHANGE}",
reply_markup=sex_keyboard(["Male", "Female"]),
)
elif column == "location":
message = await callback.message.answer(
f"{messages.INPUT_LOCATION}\n{messages.CANCEL_CHANGE}",
)
await state.update_data(
column=column,
profile_message_id=callback.message.message_id,
input_message_id=message.message_id,
)
await state.set_state(UserAlteringState.value)
await callback.answer()
@router.message(UserAlteringState.value, F.text, Registered())
async def profile_change_entered(message: Message, state: FSMContext) -> None:
if (
message.text is None
or message.from_user is None
or message.bot is None
):
return
column = (await state.get_data()).get("column")
value = message.text.strip()
if value == "/cancel":
await message.answer(
messages.CHANGE_CANCELED,
reply_markup=ReplyKeyboardRemove(),
)
await state.update_data(successfully=True)
await message.delete()
await delete_message_from_state(
state,
message.chat.id,
message.bot,
)
await state.clear()
return
if column == "username":
try:
validated_title = User().validate_username(
key="username",
value=value,
)
except AssertionError as e:
await handle_validation_error(message, state, e)
return
await state.update_data(value=validated_title, successfully=True)
elif column == "age":
try:
validated_age = User().validate_age(key="age", value=value)
except AssertionError as e:
await handle_validation_error(message, state, e)
return
await state.update_data(value=validated_age, successfully=True)
elif column == "bio":
if value == "/skip":
await state.update_data(value=None, successfully=True)
await delete_message_from_state(
state,
message.chat.id,
message.bot,
)
else:
try:
validated_bio = User().validate_bio(key="bio", value=value)
except AssertionError as e:
await handle_validation_error(message, state, e)
return
await state.update_data(value=validated_bio, successfully=True)
elif column == "sex":
value = value.lower()
try:
validated_sex = User().validate_sex(key="sex", value=value)
except AssertionError as e:
await handle_validation_error(message, state, e)
return
await state.update_data(value=validated_sex, successfully=True)
elif column == "location":
location = value.split(", ")
proccessing_message = await message.answer(messages.PROCCESSING)
if len(location) != 2:
await delete_message_from_state(
state,
message.chat.id,
message.bot,
)
await proccessing_message.edit_text(messages.VALIDATION_ERROR)
await message.delete()
error_message = proccessing_message
await state.update_data(
error_message_id=error_message.message_id,
)
return
country, city = location
try:
validated_country = User().validate_country(
key="country",
value=country,
)
except AssertionError as e:
await delete_message_from_state(
state,
message.chat.id,
message.bot,
)
await proccessing_message.edit_text("" + str(e))
await message.delete()
error_message = proccessing_message
await state.update_data(
error_message_id=error_message.message_id,
)
return
try:
validated_city = User().validate_city(
city=city,
country=validated_country,
)
except AssertionError as e:
await delete_message_from_state(
state,
message.chat.id,
message.bot,
)
await proccessing_message.edit_text("" + str(e))
await message.delete()
error_message = proccessing_message
await state.update_data(
error_message_id=error_message.message_id,
)
return
await delete_message_from_state(state, message.chat.id, message.bot)
await state.update_data(
value=[validated_country, validated_city],
successfully=True,
)
await message.delete()
await delete_message_from_state(state, message.chat.id, message.bot)
state_data = await state.get_data()
user = User.get_user_queryset_by_telegram_id(message.from_user.id)
user_first = user.first()
if isinstance(state_data["value"], list):
old_value = user_first.country + ", " + user_first.city
new_value = state_data["value"][0] + ", " + state_data["value"][1]
user.update(
{
"country": state_data["value"][0],
"city": state_data["value"][1],
},
)
try:
await proccessing_message.delete()
except TelegramBadRequest:
pass
else:
old_value = getattr(user.first(), str(column))
new_value = state_data["value"]
data = {state_data["column"]: state_data["value"]}
user.update(data)
session.commit()
user = user.first()
session.refresh(user)
try:
await message.bot.edit_message_text(
user.get_profile_text(),
message.chat.id,
state_data["profile_message_id"],
reply_markup=get(),
)
except TelegramBadRequest:
pass
await message.answer(
messages.PROFILE_UPDATED.format(
key=state_data["column"],
old_value=old_value if old_value else messages.NOT_SET,
new_value=(new_value if new_value else messages.NOT_SET),
),
reply_markup=ReplyKeyboardRemove(),
)
await state.clear()