You've already forked Travel-Agent
feat: Added travel deletion and added ability to add locations
This commit is contained in:
+375
-26
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user