diff --git a/app/callbacks/profile.py b/app/callbacks/profile.py
index 4b0d969..8a7d4d1 100644
--- a/app/callbacks/profile.py
+++ b/app/callbacks/profile.py
@@ -12,7 +12,7 @@ from app.filters.user_filter import Registered, RegisteredCallback
from app.keyboards.builders import profile
from app.keyboards.profile import get
from app.models.user import User
-from app.utils.states import UserAltering
+from app.utils.states import delete_message_from_state, UserAltering
router = Router(name="profile_callback")
@@ -33,22 +33,23 @@ async def profile_change_callback(
column = callback.data.replace("profile_change_", "")
if column == "username":
- await callback.message.answer(messages.EDIT_USERNAME)
+ message = await callback.message.answer(messages.EDIT_USERNAME)
elif column == "age":
- await callback.message.answer(messages.INPUT_AGE)
+ message = await callback.message.answer(messages.INPUT_AGE)
elif column == "bio":
- await callback.message.answer(messages.EDIT_BIO)
+ message = await callback.message.answer(messages.EDIT_BIO)
elif column == "sex":
- await callback.message.answer(
+ message = await callback.message.answer(
messages.INPUT_SEX,
reply_markup=profile(["Male", "Female"]),
)
elif column == "location":
- await callback.message.answer(messages.INPUT_LOCATION)
+ message = await callback.message.answer(messages.INPUT_LOCATION)
await state.update_data(
column=column,
message_id=callback.message.message_id,
+ input_message=message,
)
await state.set_state(UserAltering.value)
@@ -67,41 +68,72 @@ async def profile_change_entered(message: Message, state: FSMContext) -> None:
value=value,
)
except AssertionError as e:
- await message.answer(str(e))
+ await message.delete()
+ await delete_message_from_state(state)
+
+ error_message = await message.answer(str(e))
+ await state.update_data(previous_message=error_message)
+
return
- await state.update_data(value=validated_value)
+ await state.update_data(value=validated_value, successfully=True)
elif column == "age":
try:
validated_age = User().validate_age(key="age", value=value)
except AssertionError as e:
- await message.answer(str(e))
+ await message.delete()
+ await delete_message_from_state(state)
+
+ error_message = await message.answer(str(e))
+ await state.update_data(previous_message=error_message)
+
return
- await state.update_data(value=validated_age)
+ await state.update_data(value=validated_age, successfully=True)
elif column == "bio":
if value == "/skip":
- await state.update_data(value=None)
+ await state.update_data(value=None, successfully=True)
+ await delete_message_from_state(state)
else:
try:
validated_bio = User().validate_bio(key="bio", value=value)
except AssertionError as e:
- await message.answer(str(e))
+ await message.delete()
+ await delete_message_from_state(state)
+
+ error_message = await message.answer(str(e))
+ await state.update_data(previous_message=error_message)
+
return
- await state.update_data(value=validated_bio)
+ await state.update_data(value=validated_bio, successfully=True)
elif column == "sex":
value = value.lower()
- if value not in ["male", "female"]:
- await message.answer(messages.VALIDATION_ERROR_MESSAGE)
+ try:
+ validated_sex = User().validate_sex(key="sex", value=value)
+ except AssertionError as e:
+ await message.delete()
+ await delete_message_from_state(state)
+
+ error_message = await message.answer(str(e))
+ await state.update_data(previous_message=error_message)
+
return
- await state.update_data(value=value)
+ await state.update_data(value=validated_sex, successfully=True)
elif column == "location":
location = value.split(", ")
+
if len(location) != 2:
- await message.answer(messages.VALIDATION_ERROR_MESSAGE)
+ await message.delete()
+ await delete_message_from_state(state)
+
+ error_message = await message.answer(
+ messages.VALIDATION_ERROR_MESSAGE,
+ )
+ await state.update_data(previous_message=error_message)
+
return
country, city = location
@@ -112,7 +144,12 @@ async def profile_change_entered(message: Message, state: FSMContext) -> None:
value=country,
)
except AssertionError as e:
- await message.answer(str(e))
+ await message.delete()
+ await delete_message_from_state(state)
+
+ error_message = await message.answer(str(e))
+ await state.update_data(previous_message=error_message)
+
return
try:
@@ -121,11 +158,20 @@ async def profile_change_entered(message: Message, state: FSMContext) -> None:
country=validated_country,
)
except AssertionError as e:
- await message.answer(str(e))
+ await message.delete()
+ await delete_message_from_state(state)
+
+ error_message = await message.answer(str(e))
+ await state.update_data(previous_message=error_message)
+
return
+ await delete_message_from_state(state)
+
await state.update_data(value=[validated_country, validated_city])
+ await delete_message_from_state(state)
+
state_data = await state.get_data()
user = User.get_user_queryset_by_telegram_id(message.from_user.id)
@@ -163,8 +209,9 @@ async def profile_change_entered(message: Message, state: FSMContext) -> None:
except TelegramBadRequest:
pass
+ await message.delete()
await message.answer(
- "✅ Profile updated",
+ messages.PROFILE_UPDATED,
reply_markup=ReplyKeyboardRemove(),
)
diff --git a/app/handlers/start_command.py b/app/handlers/start_command.py
index 5d73201..e58a903 100644
--- a/app/handlers/start_command.py
+++ b/app/handlers/start_command.py
@@ -8,7 +8,7 @@ from aiogram.types import Message, ReplyKeyboardRemove
from app import messages, session
from app.keyboards.builders import profile
from app.models.user import User
-from app.utils.states import RegistrationForm
+from app.utils.states import delete_message_from_state, RegistrationForm
router = Router(name="start_command")
@@ -51,9 +51,16 @@ async def username_handler(message: Message, state: FSMContext) -> None:
value=username,
)
except AssertionError as e:
- await message.answer(str(e))
+ await message.delete()
+ await delete_message_from_state(state)
+
+ error_message = await message.answer(str(e))
+ await state.update_data(previous_message=error_message)
+
return
+ await delete_message_from_state(state)
+
await state.update_data(username=validated_username)
await state.set_state(RegistrationForm.age)
@@ -76,9 +83,16 @@ async def age_handler(message: Message, state: FSMContext) -> None:
try:
validated_age = User().validate_age(key="age", value=age)
except AssertionError as e:
- await message.answer(str(e))
+ await message.delete()
+ await delete_message_from_state(state)
+
+ error_message = await message.answer(str(e))
+ await state.update_data(previous_message=error_message)
+
return
+ await delete_message_from_state(state)
+
await state.update_data(age=validated_age)
await state.set_state(RegistrationForm.sex)
@@ -98,11 +112,20 @@ async def sex_handler(message: Message, state: FSMContext) -> None:
sex = message.text.strip().lower()
- if sex not in ["male", "female"]:
- await message.answer(messages.VALIDATION_ERROR_MESSAGE)
+ try:
+ validated_sex = User().validate_sex(key="sex", value=sex)
+ except AssertionError as e:
+ await message.delete()
+ await delete_message_from_state(state)
+
+ error_message = await message.answer(str(e))
+ await state.update_data(previous_message=error_message)
+
return
- await state.update_data(sex=sex)
+ await delete_message_from_state(state)
+
+ await state.update_data(sex=validated_sex)
await state.set_state(RegistrationForm.bio)
await message.answer(
@@ -123,15 +146,24 @@ async def bio_handler(message: Message, state: FSMContext) -> None:
await state.update_data(bio=None)
await state.set_state(RegistrationForm.location)
+ await delete_message_from_state(state)
+
await message.answer(messages.INPUT_BIO_SKIPPED)
await message.answer(messages.INPUT_LOCATION)
else:
try:
validated_bio = User().validate_bio(key="bio", value=bio)
except AssertionError as e:
- await message.answer(str(e))
+ await message.delete()
+ await delete_message_from_state(state)
+
+ error_message = await message.answer(str(e))
+ await state.update_data(previous_message=error_message)
+
return
+ await delete_message_from_state(state)
+
await state.update_data(bio=validated_bio)
await state.set_state(RegistrationForm.location)
@@ -149,7 +181,12 @@ async def location_handler(message: Message, state: FSMContext) -> None:
location = message.text.strip().split(", ")
if len(location) != 2:
- await message.answer(messages.VALIDATION_ERROR_MESSAGE)
+ await message.delete()
+ await delete_message_from_state(state)
+
+ error_message = await message.answer(messages.VALIDATION_ERROR_MESSAGE)
+ await state.update_data(previous_message=error_message)
+
return
country, city = location
@@ -160,7 +197,12 @@ async def location_handler(message: Message, state: FSMContext) -> None:
value=country,
)
except AssertionError as e:
- await message.answer(str(e))
+ await message.delete()
+ await delete_message_from_state(state)
+
+ error_message = await message.answer(str(e))
+ await state.update_data(previous_message=error_message)
+
return
try:
@@ -169,9 +211,16 @@ async def location_handler(message: Message, state: FSMContext) -> None:
country=validated_country,
)
except AssertionError as e:
- await message.answer(str(e))
+ await message.delete()
+ await delete_message_from_state(state)
+
+ error_message = await message.answer(str(e))
+ await state.update_data(previous_message=error_message)
+
return
+ await delete_message_from_state(state)
+
await state.update_data(location=[validated_country, validated_city])
data = await state.get_data()
await state.clear()
@@ -187,6 +236,8 @@ async def location_handler(message: Message, state: FSMContext) -> None:
data["country"] = data["location"][0]
data["city"] = data["location"][1]
del data["location"]
+ del data["previous_message"]
+
session.add(User(**data))
session.commit()
diff --git a/app/messages.py b/app/messages.py
index 0419dd8..db287d0 100644
--- a/app/messages.py
+++ b/app/messages.py
@@ -21,10 +21,11 @@ PROFILE = (
"\tUsername: {username}\n"
"\tAge: {age}\n"
"\tSex: {sex}\n"
- "\tBio: {bio}\n"
"\tCountry: {country}\n"
"\tCity: {city}"
+ "\tBio: {bio}\n"
)
NOT_SET = "Not set"
EDIT_USERNAME = "Enter your username:\nAllowed characters: a-z, A-Z, 0-9, _\nLength: 5-20 characters"
EDIT_BIO = "Enter your bio (enter /skip if you want to set it to None):\nMaximum length: 100 characters"
+PROFILE_UPDATED = "✅ Profile updated"
diff --git a/app/utils/states.py b/app/utils/states.py
index 65dd129..6aee704 100644
--- a/app/utils/states.py
+++ b/app/utils/states.py
@@ -1,9 +1,12 @@
__all__ = ("RegistrationForm",)
+from aiogram.exceptions import TelegramBadRequest
from aiogram.fsm.state import State, StatesGroup
+from aiogram.fsm.context import FSMContext
class RegistrationForm(StatesGroup):
+ previous_message = State()
username = State()
age = State()
bio = State()
@@ -12,6 +15,34 @@ class RegistrationForm(StatesGroup):
class UserAltering(StatesGroup):
+ successfully = State()
message_id = State()
+ input_message = State()
+ previous_message = State()
column = State()
value = State()
+
+
+async def delete_message_from_state(state: FSMContext) -> None:
+ data = await state.get_data()
+
+ if "previous_message" in data and data["previous_message"] is not None:
+ try:
+ await data["previous_message"].delete()
+ except TelegramBadRequest:
+ pass
+
+ await state.update_data(previous_message=None)
+
+ if (
+ "input_message" in data
+ and data["input_message"] is not None
+ and "successfully" in data
+ and data["successfully"]
+ ):
+ try:
+ await data["input_message"].delete()
+ except TelegramBadRequest:
+ pass
+
+ await state.update_data(info_message=None)