feat: Added travel deletion and added ability to add locations

This commit is contained in:
ITQ
2024-03-25 02:51:25 +03:00
parent dd16eda94a
commit 65719a61ef
9 changed files with 520 additions and 42 deletions
+375 -26
View File
@@ -1,5 +1,7 @@
__all__ = ("router",)
import datetime
from aiogram import F, Router
from aiogram.exceptions import TelegramBadRequest
from aiogram.filters import StateFilter
@@ -10,10 +12,11 @@ from app import messages, session
from app.config import Config
from app.filters.user import Registered, RegisteredCallback
from app.keyboards.builders import travels_keyboard
from app.keyboards.travel import get
from app.models.travel import Travel
from app.keyboards.confirm_location import get as confirm_location_get
from app.keyboards.travel import get as travel_get
from app.models.travel import Location, Travel
from app.models.user import User
from app.states.travel import TravelAlteringState
from app.states.travel import CreateLocationState, TravelAlteringState
from app.utils.states import delete_message_from_state, handle_validation_error
@@ -36,19 +39,25 @@ async def travels_index_callback(callback: CallbackQuery) -> None:
travels = user.get_user_travels()
if not travels or travels == []:
await callback.message.edit_text(messages.NO_TRAVELS)
try:
await callback.message.edit_text(messages.NO_TRAVELS)
except TelegramBadRequest:
pass
else:
pages = (len(travels) + Config.PAGE_SIZE - 1) // Config.PAGE_SIZE
await callback.message.edit_text(
messages.TRAVELS,
reply_markup=travels_keyboard(
travels,
page,
pages,
user.telegram_id,
),
)
try:
await callback.message.edit_text(
messages.TRAVELS,
reply_markup=travels_keyboard(
travels,
page,
pages,
user.telegram_id,
),
)
except TelegramBadRequest:
pass
@router.callback_query(
@@ -74,15 +83,18 @@ async def travels_callback(callback: CallbackQuery) -> None:
else:
pages = (len(travels) + Config.PAGE_SIZE - 1) // Config.PAGE_SIZE
await callback.message.edit_text(
messages.TRAVELS,
reply_markup=travels_keyboard(
travels,
page,
pages,
user.telegram_id,
),
)
try:
await callback.message.edit_text(
messages.TRAVELS,
reply_markup=travels_keyboard(
travels,
page,
pages,
user.telegram_id,
),
)
except TelegramBadRequest:
pass
@router.callback_query(
@@ -103,7 +115,7 @@ async def travel_detail_callback(callback: CallbackQuery) -> None:
await callback.message.edit_text(
travel.get_travel_text(),
reply_markup=get(travel_id),
reply_markup=travel_get(travel_id),
)
@@ -125,6 +137,11 @@ async def travel_change_callback(
travel_id, column = callback.data.replace("travel_change_", "").split("_")
travel = Travel().get_travel_by_id(travel_id)
if not travel:
return
if column == "title":
message = await callback.message.answer(
f"{messages.INPUT_TRAVEL_TITLE}\n{messages.CANCEL_CHANGE}",
@@ -199,7 +216,8 @@ async def travel_change_entered(message: Message, state: FSMContext) -> None:
else:
try:
validated_description = Travel().validate_description(
key="description", value=value,
key="description",
value=value,
)
except AssertionError as e:
await handle_validation_error(message, state, e)
@@ -207,7 +225,8 @@ async def travel_change_entered(message: Message, state: FSMContext) -> None:
return
await state.update_data(
value=validated_description, successfully=True,
value=validated_description,
successfully=True,
)
await message.delete()
@@ -230,7 +249,7 @@ async def travel_change_entered(message: Message, state: FSMContext) -> None:
travel.get_travel_text(),
message.chat.id,
state_data["travel_message_id"],
reply_markup=get(travel_id),
reply_markup=travel_get(travel_id),
)
except TelegramBadRequest:
pass
@@ -240,3 +259,333 @@ async def travel_change_entered(message: Message, state: FSMContext) -> None:
)
await state.clear()
@router.callback_query(
F.data.startswith("travel_add_location"),
RegisteredCallback(),
StateFilter(None),
)
async def add_travel_location_callback(
callback: CallbackQuery,
state: FSMContext,
) -> None:
if (
callback.data is None
or callback.message is None
or not isinstance(callback.message, Message)
):
return
travel_id = int(callback.data.replace("travel_add_location_", ""))
travel = Travel().get_travel_by_id(travel_id)
if not travel:
return
await state.update_data(travel_id=travel_id)
await state.set_state(CreateLocationState.temp_location)
await callback.message.answer(
messages.CREATE_LOCATION,
)
await callback.message.answer(
messages.ENTER_LOCATION,
)
await callback.answer()
@router.message(CreateLocationState.temp_location, F.text, Registered())
async def location_entered(message: Message, state: FSMContext) -> None:
if (
message.text is None
or message.from_user is None
or message.bot is None
):
return
location = message.text.strip()
if location == "/cancel":
await message.answer(
messages.ACTION_CANCELED,
)
await state.update_data()
await message.delete()
await delete_message_from_state(
state,
message.chat.id,
message.bot,
)
await state.clear()
return
try:
validated_location = Location().validate_location(
key="location",
value=location,
)
except AssertionError as e:
await handle_validation_error(message, state, e)
return
await delete_message_from_state(state, message.chat.id, message.bot)
await state.update_data(
temp_location=validated_location,
temp_location_message_id=message.message_id,
)
await state.set_state(CreateLocationState.location)
await message.answer(
messages.CONFIRM_LOCATION.format(location=validated_location),
reply_markup=confirm_location_get(),
)
@router.callback_query(
F.data.in_(["confirm_location", "cancel_location"]),
RegisteredCallback(),
StateFilter(CreateLocationState.location),
)
async def confirm_location(
callback: CallbackQuery,
state: FSMContext,
) -> None:
if (
not callback.message
or not isinstance(callback.message, Message)
or callback.bot is None
):
return
data = await state.get_data()
location = data.get("temp_location")
if callback.data == "confirm_location":
await delete_message_from_state(
state,
callback.from_user.id,
callback.bot,
)
await state.update_data(location=location)
await state.set_state(CreateLocationState.date_start)
await callback.message.answer(
messages.INPUT_TRAVEL_CALLBACK.format(
key="location",
value=location,
),
)
await callback.message.answer(
messages.ENTER_LOCATION_DATE_START,
)
elif callback.data == "cancel_location":
error_message = await callback.message.answer(
messages.CONFIRMATION_REEJECTED,
)
try:
await callback.bot.delete_message(
callback.from_user.id,
data["temp_location_message_id"],
)
except TelegramBadRequest:
pass
await state.set_state(CreateLocationState.temp_location)
await state.update_data(error_message_id=error_message.message_id)
try:
await callback.message.delete()
except TelegramBadRequest:
pass
await callback.answer()
@router.message(CreateLocationState.date_start, F.text, Registered())
async def location_date_start_entered(
message: Message,
state: FSMContext,
) -> None:
if (
message.text is None
or message.from_user is None
or message.bot is None
):
return
date_start = message.text.strip()
if date_start == "/cancel":
await message.answer(
messages.ACTION_CANCELED,
)
await state.update_data()
await message.delete()
await delete_message_from_state(
state,
message.chat.id,
message.bot,
)
await state.clear()
return
try:
validated_date_start = Location().validate_date_end(
key="date_start",
value=date_start,
)
except AssertionError as e:
await handle_validation_error(message, state, e)
return
await delete_message_from_state(state, message.chat.id, message.bot)
await state.update_data(
date_start=datetime.datetime.strftime(
validated_date_start,
"%Y-%m-%d %H:%M:%S",
),
)
await state.set_state(CreateLocationState.date_end)
await message.answer(
messages.INPUT_TRAVEL_CALLBACK.format(
key="start date",
value=date_start,
),
)
await message.answer(
messages.ENTER_LOCATION_DATE_END,
)
@router.message(CreateLocationState.date_end, F.text, Registered())
async def location_date_end_entered(
message: Message,
state: FSMContext,
) -> None:
if (
message.text is None
or message.from_user is None
or message.bot is None
):
return
date_end = message.text.strip()
if date_end == "/cancel":
await message.answer(
messages.ACTION_CANCELED,
)
await state.update_data()
await message.delete()
await delete_message_from_state(
state,
message.chat.id,
message.bot,
)
await state.clear()
return
try:
validated_date_end = Location().validate_date_end(
key="date_end",
value=date_end,
)
except AssertionError as e:
await handle_validation_error(message, state, e)
return
date_start = (await state.get_data()).get("date_start")
if validated_date_end <= datetime.datetime.strptime(
str(date_start),
"%Y-%m-%d %H:%M:%S",
).replace(tzinfo=datetime.UTC):
await handle_validation_error(
message,
state,
messages.INVALID_DATE_END,
)
return
await delete_message_from_state(state, message.chat.id, message.bot)
await state.update_data(
date_end=datetime.datetime.strftime(
validated_date_end,
"%Y-%m-%d %H:%M:%S",
),
)
data = await state.get_data()
if "temp_location" in data:
del data["temp_location"]
if "temp_location_message_id" in data:
del data["temp_location_message_id"]
if "error_message_id" in data:
del data["error_message_id"]
data["date_start"] = datetime.datetime.strptime(
data["date_start"],
"%Y-%m-%d %H:%M:%S",
)
data["date_end"] = datetime.datetime.strptime(
data["date_end"],
"%Y-%m-%d %H:%M:%S",
)
session.add(Location(**data))
session.commit()
await message.answer(
messages.LOCATION_ADDED,
)
await state.clear()
@router.callback_query(
F.data.startswith("travel_delete"),
RegisteredCallback(),
StateFilter(None),
)
async def delete_travel_callback(
callback: CallbackQuery,
):
if callback.data is None or not isinstance(callback.message, Message):
return
travel_id = int(callback.data.replace("travel_delete_", ""))
travel = Travel.get_travel_queryset_by_id(travel_id)
travel.delete()
session.commit()
await callback.message.answer(messages.DELETED_TRAVEL)
await callback.message.delete()
await callback.answer()