You've already forked Travel-Agent
chore: Added __init__ files, added fallback for callbacks, refactoring & improvements
This commit is contained in:
+14
-22
@@ -6,17 +6,8 @@ from aiogram import Bot, Dispatcher
|
||||
from aiogram.enums import ParseMode
|
||||
from aiogram.fsm.storage.redis import RedisStorage
|
||||
|
||||
from app.callbacks import location, menu, notes, profile, travel
|
||||
from app import callbacks, handlers, middlewares
|
||||
from app.config import Config
|
||||
from app.handlers import (
|
||||
create_travel_command,
|
||||
help_command,
|
||||
menu_command,
|
||||
profile_command,
|
||||
start_command,
|
||||
travels_command,
|
||||
)
|
||||
from app.middlewares.throttling import ThrottlingMiddleware
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
@@ -29,20 +20,21 @@ async def main() -> None:
|
||||
dp = Dispatcher(storage=storage)
|
||||
bot = Bot(bot_token, parse_mode=ParseMode.HTML)
|
||||
|
||||
dp.message.middleware(ThrottlingMiddleware(0.5))
|
||||
dp.message.middleware(middlewares.throttling.ThrottlingMiddleware(0.5))
|
||||
|
||||
dp.include_routers(
|
||||
start_command.router,
|
||||
help_command.router,
|
||||
menu_command.router,
|
||||
profile_command.router,
|
||||
create_travel_command.router,
|
||||
travels_command.router,
|
||||
menu.router,
|
||||
profile.router,
|
||||
travel.router,
|
||||
location.router,
|
||||
notes.router,
|
||||
handlers.start_command.router,
|
||||
handlers.help_command.router,
|
||||
handlers.menu_command.router,
|
||||
handlers.profile_command.router,
|
||||
handlers.create_travel_command.router,
|
||||
handlers.travels_command.router,
|
||||
callbacks.menu.router,
|
||||
callbacks.profile.router,
|
||||
callbacks.travel.router,
|
||||
callbacks.location.router,
|
||||
callbacks.notes.router,
|
||||
callbacks.fallback.router,
|
||||
)
|
||||
|
||||
await bot.delete_webhook(drop_pending_updates=True)
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
__all__ = ("fallback", "location", "menu", "profile", "travel", "notes")
|
||||
|
||||
from app.callbacks import fallback, location, menu, notes, profile, travel
|
||||
@@ -0,0 +1,17 @@
|
||||
__all__ = ("router",)
|
||||
|
||||
from aiogram import Router
|
||||
from aiogram.filters import StateFilter
|
||||
from aiogram.types import CallbackQuery
|
||||
|
||||
router = Router(name="fallback_callback")
|
||||
|
||||
|
||||
@router.callback_query(~StateFilter(None))
|
||||
async def in_state_callback(callback: CallbackQuery):
|
||||
await callback.answer("Fallback text in state", show_alert=True)
|
||||
|
||||
|
||||
@router.callback_query()
|
||||
async def fallback_callback(callback: CallbackQuery):
|
||||
await callback.answer("Fallback text", show_alert=True)
|
||||
+29
-7
@@ -17,7 +17,7 @@ from app.states.travel import (
|
||||
)
|
||||
|
||||
|
||||
router = Router(name="menu_callback")
|
||||
router = Router(name="notes_callback")
|
||||
|
||||
|
||||
@router.callback_query(
|
||||
@@ -110,12 +110,26 @@ async def create_note_file_id(message: Message, state: FSMContext):
|
||||
|
||||
data["author_id"] = message.from_user.id
|
||||
|
||||
session.add(Note(**data))
|
||||
note = Note(**data)
|
||||
|
||||
session.add(note)
|
||||
|
||||
session.commit()
|
||||
|
||||
if not note or note == []:
|
||||
return
|
||||
|
||||
if note.file_type == "photo":
|
||||
file_name = f"Photo ID: {note.id}"
|
||||
elif note.file_type == "video":
|
||||
file_name = f"Video ID: {note.id}"
|
||||
elif note.file_type == "voice":
|
||||
file_name = f"Voice ID: {note.id}"
|
||||
else:
|
||||
file_name = note.file_name
|
||||
|
||||
await message.answer(
|
||||
messages.NOTE_ADDED.format(file_name=data["file_name"]),
|
||||
messages.NOTE_ADDED.format(file_name=file_name),
|
||||
)
|
||||
|
||||
await state.clear()
|
||||
@@ -299,13 +313,21 @@ async def travel_notedelete_callback(
|
||||
|
||||
note = Note().get_note_queryset_by_id(note_id)
|
||||
|
||||
note_first = note.first()
|
||||
file_name = note_first.file_name
|
||||
travel = note_first.travel
|
||||
|
||||
if not note or note == []:
|
||||
return
|
||||
|
||||
note_first = note.first()
|
||||
travel = note_first.travel
|
||||
|
||||
if note_first.file_type == "photo":
|
||||
file_name = f"Photo ID: {note_first.id}"
|
||||
elif note_first.file_type == "video":
|
||||
file_name = f"Video ID: {note_first.id}"
|
||||
elif note_first.file_type == "voice":
|
||||
file_name = f"Voice ID: {note_first.id}"
|
||||
else:
|
||||
file_name = note_first.file_name
|
||||
|
||||
note.delete()
|
||||
|
||||
session.commit()
|
||||
|
||||
+34
-1
@@ -11,6 +11,7 @@ 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 as travel_get
|
||||
from app.keyboards.routes import get as routes_get
|
||||
from app.models.travel import Travel
|
||||
from app.models.user import User
|
||||
from app.states.travel import (
|
||||
@@ -19,7 +20,7 @@ from app.states.travel import (
|
||||
from app.utils.states import delete_message_from_state, handle_validation_error
|
||||
|
||||
|
||||
router = Router(name="menu_callback")
|
||||
router = Router(name="travel_callback")
|
||||
|
||||
|
||||
@router.callback_query(
|
||||
@@ -301,3 +302,35 @@ async def delete_travel_callback(
|
||||
)
|
||||
|
||||
await callback.answer()
|
||||
|
||||
|
||||
@router.callback_query(
|
||||
F.data.startswith("travel_routes"),
|
||||
RegisteredCallback(),
|
||||
StateFilter(None),
|
||||
)
|
||||
async def travel_routes_callback(
|
||||
callback: CallbackQuery,
|
||||
):
|
||||
if (
|
||||
callback.message is None
|
||||
or callback.data is None
|
||||
or not isinstance(callback.message, Message)
|
||||
):
|
||||
return
|
||||
|
||||
travel_id = int(callback.data.replace("travel_routes_", ""))
|
||||
|
||||
travel = Travel().get_travel_by_id(travel_id)
|
||||
|
||||
if not travel:
|
||||
await callback.answer()
|
||||
|
||||
return
|
||||
|
||||
await callback.message.edit_text(
|
||||
travel.get_travel_text(),
|
||||
reply_markup=routes_get(travel),
|
||||
)
|
||||
|
||||
await callback.answer()
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
__all__ = (
|
||||
"start_command",
|
||||
"help_command",
|
||||
"menu_command",
|
||||
"profile_command",
|
||||
"create_travel_command",
|
||||
"travels_command",
|
||||
)
|
||||
|
||||
from app.handlers import (
|
||||
create_travel_command,
|
||||
help_command,
|
||||
menu_command,
|
||||
profile_command,
|
||||
start_command,
|
||||
travels_command,
|
||||
)
|
||||
@@ -0,0 +1,63 @@
|
||||
__all__ = ("get",)
|
||||
|
||||
from aiogram import types
|
||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||
|
||||
from app.models.travel import Travel
|
||||
from app.utils.geo import get_location_by_name
|
||||
from app.utils.map import get_url_map
|
||||
|
||||
|
||||
def get(travel: Travel):
|
||||
locations = Travel().get_sorted_locations(travel, asc=False)
|
||||
coordinats = []
|
||||
|
||||
for location in locations:
|
||||
geocode = get_location_by_name(location.location)
|
||||
coordinats.append(
|
||||
[geocode[1].raw.get("lat"), geocode[1].raw.get("lon")],
|
||||
)
|
||||
|
||||
builder = InlineKeyboardBuilder()
|
||||
|
||||
builder.row(
|
||||
types.InlineKeyboardButton(
|
||||
text="🗺️ Route by car",
|
||||
web_app=types.WebAppInfo(
|
||||
url=get_url_map(
|
||||
coordinats=coordinats,
|
||||
profile="car",
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
builder.row(
|
||||
types.InlineKeyboardButton(
|
||||
text="🗺️ Route on foot",
|
||||
web_app=types.WebAppInfo(
|
||||
url=get_url_map(
|
||||
coordinats=coordinats,
|
||||
profile="foot",
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
builder.row(
|
||||
types.InlineKeyboardButton(
|
||||
text="🗺️ Route by bike",
|
||||
web_app=types.WebAppInfo(
|
||||
url=get_url_map(
|
||||
coordinats=coordinats,
|
||||
profile="bike",
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
builder.row(
|
||||
types.InlineKeyboardButton(
|
||||
text="⬅️",
|
||||
callback_data=f"travel_detail_{travel.id}",
|
||||
),
|
||||
)
|
||||
|
||||
return builder.as_markup()
|
||||
+4
-78
@@ -4,20 +4,9 @@ from aiogram import types
|
||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||
|
||||
from app.models.travel import Travel
|
||||
from app.utils.geo import get_location_by_name
|
||||
from app.utils.map import get_url_map
|
||||
|
||||
|
||||
def get(travel: Travel):
|
||||
locations = Travel().get_sorted_locations(travel, asc=False)
|
||||
coordinats = []
|
||||
|
||||
for location in locations:
|
||||
geocode = get_location_by_name(location.location)
|
||||
coordinats.append(
|
||||
[geocode[1].raw.get("lat"), geocode[1].raw.get("lon")],
|
||||
)
|
||||
|
||||
builder = InlineKeyboardBuilder()
|
||||
|
||||
builder.row(
|
||||
@@ -62,35 +51,8 @@ def get(travel: Travel):
|
||||
)
|
||||
builder.row(
|
||||
types.InlineKeyboardButton(
|
||||
text="🗺️ Route by car",
|
||||
web_app=types.WebAppInfo(
|
||||
url=get_url_map(
|
||||
coordinats=coordinats,
|
||||
profile="car",
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
builder.row(
|
||||
types.InlineKeyboardButton(
|
||||
text="🗺️ Route on foot",
|
||||
web_app=types.WebAppInfo(
|
||||
url=get_url_map(
|
||||
coordinats=coordinats,
|
||||
profile="foot",
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
builder.row(
|
||||
types.InlineKeyboardButton(
|
||||
text="🗺️ Route by bike",
|
||||
web_app=types.WebAppInfo(
|
||||
url=get_url_map(
|
||||
coordinats=coordinats,
|
||||
profile="bike",
|
||||
),
|
||||
),
|
||||
text="🗺️ Routes",
|
||||
callback_data=f"travel_routes_{travel.id}",
|
||||
),
|
||||
)
|
||||
builder.row(
|
||||
@@ -110,15 +72,6 @@ def get(travel: Travel):
|
||||
|
||||
|
||||
def get_public(travel: Travel):
|
||||
locations = Travel().get_sorted_locations(travel, asc=False)
|
||||
coordinats = []
|
||||
|
||||
for location in locations:
|
||||
geocode = get_location_by_name(location.location)
|
||||
coordinats.append(
|
||||
[geocode[1].raw.get("lat"), geocode[1].raw.get("lon")],
|
||||
)
|
||||
|
||||
builder = InlineKeyboardBuilder()
|
||||
|
||||
builder.row(
|
||||
@@ -145,35 +98,8 @@ def get_public(travel: Travel):
|
||||
)
|
||||
builder.row(
|
||||
types.InlineKeyboardButton(
|
||||
text="🗺️ Route by car",
|
||||
web_app=types.WebAppInfo(
|
||||
url=get_url_map(
|
||||
coordinats=coordinats,
|
||||
profile="car",
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
builder.row(
|
||||
types.InlineKeyboardButton(
|
||||
text="🗺️ Route on foot",
|
||||
web_app=types.WebAppInfo(
|
||||
url=get_url_map(
|
||||
coordinats=coordinats,
|
||||
profile="foot",
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
builder.row(
|
||||
types.InlineKeyboardButton(
|
||||
text="🗺️ Route by bike",
|
||||
web_app=types.WebAppInfo(
|
||||
url=get_url_map(
|
||||
coordinats=coordinats,
|
||||
profile="bike",
|
||||
),
|
||||
),
|
||||
text="🗺️ Routes",
|
||||
callback_data=f"travel_routes_{travel.id}",
|
||||
),
|
||||
)
|
||||
builder.row(
|
||||
|
||||
+106
-29
@@ -1,10 +1,24 @@
|
||||
# flake8: noqa
|
||||
|
||||
# Menu
|
||||
MENU = "<b>Menu:</b>"
|
||||
|
||||
# Notes
|
||||
NOTES = "📝 <b>Notes:</b>\n"
|
||||
NOTE_DETAIL = "📝 <b>Note detail:</b>\n\n\tFile name: <b>{file_name}</b>\n\tFile type: <b>{file_type}</b>\n\tPublic: <b>{public}</b>"
|
||||
NOTE_DETAIL = (
|
||||
"📝 <b>Note detail:</b>\n\n"
|
||||
"\tFile name: <b>{file_name}</b>\n"
|
||||
"\tFile type: <b>{file_type}</b>\n"
|
||||
"\tPublic: <b>{public}</b>"
|
||||
)
|
||||
ADD_NOTE = (
|
||||
"✏️ Send me a file, photo, video, or voice message to add a note."
|
||||
"\n<i>Enter /cancel to cancel creating.</i>"
|
||||
)
|
||||
NOTE_ADDED = "✅ Note <b>{file_name}</b> added successfully."
|
||||
NOTE_DELETED = "❌ Note <b>{file_name}</b> deleted."
|
||||
|
||||
# Locations
|
||||
LOCATIONS = "🗺️ <b>Locations:</b>"
|
||||
LOCATION_DELETED = "❌ Location deleted."
|
||||
LOCATION_DETAIL = (
|
||||
@@ -16,48 +30,77 @@ LOCATION_DETAIL = (
|
||||
LOCATION_WEATHER = (
|
||||
"🌤️ <b>{location} weather:</b>\n\n"
|
||||
"\t<b>☁️ Weather:</b> {weather_main}\n"
|
||||
"\t<b>🌡️ Current tempurature:</b> {temp} °C\n"
|
||||
"\t<b>🌡️ Current temperature:</b> {temp} °C\n"
|
||||
"\t<b>🤗 Feels like:</b> {feels_like} °C\n"
|
||||
"\t<b>❄️ Min. tempurature:</b> {temp_min} °C\n"
|
||||
"\t<b>🔥 Max. tempurature:</b> {temp_max} °C\n"
|
||||
"\t<b>❄️ Min. temperature:</b> {temp_min} °C\n"
|
||||
"\t<b>🔥 Max. temperature:</b> {temp_max} °C\n"
|
||||
"\t<b>⬇️ Pressure:</b> {pressure} hektopascals\n"
|
||||
"\t<b>💨 Humidity:</b> {humidity}%\n"
|
||||
)
|
||||
|
||||
# Sights
|
||||
SIGHTS_HEADER = "🗺️ <b>Sights:</b>\n"
|
||||
SIGHTS_FOOTER = "Found {sights_count} sights within {distance} m from: <b>{location}</b>."
|
||||
SIGHTS_FOOTER = (
|
||||
"Found {sights_count} sights within {distance} m from: <b>{location}</b>."
|
||||
)
|
||||
NO_SIGHTS_FOUND = (
|
||||
"No sights found within {distance} m from: <b>{location}</b>."
|
||||
)
|
||||
SIGHT_DETAIL = "🗺️ <b>Sight detail:</b>\n\n"
|
||||
CREATE_LOCATION = "✈️ Lets create new location!"
|
||||
ENTER_LOCATION = "Enter location:\n<i>Format: country, city, ... etc</i>\n<i>Example: Kremlin, Moscow, Russia</i>\n<i>Enter /cancel to cancel creating.</i>"
|
||||
|
||||
# Location Creation
|
||||
CREATE_LOCATION = "✈️ Lets create a new location!"
|
||||
ENTER_LOCATION = (
|
||||
"Enter location:\n"
|
||||
"<i>Format: country, city, ... etc</i>\n"
|
||||
"<i>Example: Kremlin, Moscow, Russia</i>\n"
|
||||
"<i>Enter /cancel to cancel creating.</i>"
|
||||
)
|
||||
CONFIRM_LOCATION = "Is this location correct: <b>{location}</b>?"
|
||||
CONFIRMATION_REEJECTED = (
|
||||
CONFIRMATION_REJECTED = (
|
||||
"❌ Confirmation rejected. Please re-enter the location."
|
||||
)
|
||||
OVERLAPPING_LOCATION = "Dates overlap with another location in the same travel(enter /cancel if you cant fix this)."
|
||||
ENTER_LOCATION_DATE_START = "Enter location start datetime(in UTC) in this format:\n<i>Format: YYYY-MM-DD HH:MM</i>\n<i>Example: 2022-01-01 00:00</i>"
|
||||
ENTER_LOCATION_DATE_END = "Enter location end datetime(in UTC) in this format:\n<i>Format: YYYY-MM-DD HH:MM</i>\n<i>Example: 2022-01-01 00:00</i>"
|
||||
OVERLAPPING_LOCATION = "Dates overlap with another location in the same travel(enter /cancel if you can't fix this)."
|
||||
ENTER_LOCATION_DATE_START = (
|
||||
"Enter location start datetime(in UTC) in this format:\n"
|
||||
"<i>Format: YYYY-MM-DD HH:MM</i>\n"
|
||||
"<i>Example: 2022-01-01 00:00</i>"
|
||||
)
|
||||
ENTER_LOCATION_DATE_END = (
|
||||
"Enter location end datetime(in UTC) in this format:\n"
|
||||
"<i>Format: YYYY-MM-DD HH:MM</i>\n"
|
||||
"<i>Example: 2022-01-01 00:00>"
|
||||
)
|
||||
INVALID_DATE_END = "End date can't be earlier or equal to start date."
|
||||
LOCATION_ADDED = "✅ Location added"
|
||||
|
||||
ADD_NOTE = "✏️ Send me file, photo, video or voice nessage to add note.\n<i>Enter /cancel to cancel creating.</i>"
|
||||
|
||||
# Travel Management
|
||||
DELETED_TRAVEL = "✅ Travel deleted"
|
||||
TRAVELS = "📃 <b>Travels:</b>\n<i>👑 - owner</i>"
|
||||
TRAVELS = (
|
||||
"📃 <b>Travels:</b>"
|
||||
"\n<i>👑 - owner</i>"
|
||||
)
|
||||
NO_TRAVELS = "No travels yet. You can create one with /create_travel command."
|
||||
CREATE_TRAVEL = (
|
||||
"🧳 Let's create new travel!\n<i>Enter /cancel to cancel creating.</i>"
|
||||
"🧳 Let's create a new travel!\n"
|
||||
"<i>Enter /cancel to cancel creating.</i>"
|
||||
)
|
||||
TRAVEL_UPDATED = "✅ Travel updated"
|
||||
EDIT_TRAVEL_DESCRIPTION = "Enter travel description (enter /skip if you want to set it to None):\n<i>Maximum length: 100 characters</i>"
|
||||
EDIT_TRAVEL_DESCRIPTION = (
|
||||
"Enter travel description (enter /skip if you want to set it to None):\n"
|
||||
"<i>Maximum length: 100 characters</i>"
|
||||
)
|
||||
INPUT_TRAVEL_TITLE = (
|
||||
"Enter travel title:\n<i>Maximum length: 30 characters</i>"
|
||||
"Enter travel title:\n"
|
||||
"<i>Maximum length: 30 characters</i>"
|
||||
)
|
||||
INPUT_TRAVEL_CALLBACK = (
|
||||
"All right, travel <b>{key}</b> is set to: <b>{value}</b>"
|
||||
)
|
||||
INPUT_TRAVEL_DESCRIPTION = "Enter travel description (enter /skip if you want to skip this step):\n<i>Maximum length: 100 characters</i>"
|
||||
INPUT_TRAVEL_DESCRIPTION = (
|
||||
"Enter travel description (enter /skip if you want to skip this step):\n"
|
||||
"<i>Maximum length: 100 characters</i>"
|
||||
)
|
||||
INPUT_TRAVEL_DESCRIPTION_SKIPPED = "✅ Sure. You can always fill it later."
|
||||
TRAVEL_CREATED = "Travel <b>{title}</b> successfully created! You can now view and edit it in the travels list (/travels command)."
|
||||
ACTION_CANCELED = "❌ Action canceled"
|
||||
@@ -68,11 +111,12 @@ TRAVEL_DETAIL = (
|
||||
"\tDescription: <b>{description}</b>\n"
|
||||
)
|
||||
|
||||
# User Interaction
|
||||
WELCOME_MESSAGE = "Hello, <b>{name}</b>! Welcome to the ✈️ Travel Agent bot! Let's start our journey by filling out some information about you."
|
||||
WELCOME_AGAIN_MESSAGE = "Hello, <b>{name}</b>! Welcome back to the ✈️ Travel Agent bot! If you get lost, you can always call the /help command for assistance."
|
||||
|
||||
HELP_MESSAGE = (
|
||||
"Welcome to the ✈️ Travel Agent bot! Here is list of commands you can use:\n\n"
|
||||
"Welcome to the ✈️ Travel Agent bot! Here is a list of commands you can use:\n\n"
|
||||
"/start - Start the bot\n"
|
||||
"/help - Show this message\n"
|
||||
"/menu - Show the main menu\n"
|
||||
@@ -83,18 +127,39 @@ HELP_MESSAGE = (
|
||||
"❓ If you have any questions/issues, feel free to contact us via @itq_travel_agent_support_bot on Telegram."
|
||||
)
|
||||
|
||||
REGISTERED_MESSAGE = "You have successfully registered. Welcome to the ✈️ Travel Agent bot! \nYou can view and edit your profile using the /profile command."
|
||||
REGISTERED_MESSAGE = (
|
||||
"You have successfully registered. Welcome to the ✈️ Travel Agent bot!\n"
|
||||
"You can view and edit your profile using the /profile command."
|
||||
)
|
||||
|
||||
INPUT_USERNAME = "Enter your username (this will be used to interact with other users):\n<i>Allowed characters: a-z, A-Z, 0-9, _</i>\n<i>Length: 5-20 characters</i>"
|
||||
INPUT_AGE = "Enter your age:\n<i>Range: 13-120</i>"
|
||||
INPUT_SEX = "Enter your sex:\n<i>Options: Male or Female</i>"
|
||||
INPUT_BIO = "Enter your bio (enter /skip if you want to skip this step):\n<i>Maximum length: 100 characters</i>"
|
||||
INPUT_USERNAME = (
|
||||
"Enter your username (this will be used to interact with other users):\n"
|
||||
"<i>Allowed characters: a-z, A-Z, 0-9, _</i>\n"
|
||||
"<i>Length: 5-20 characters</i>"
|
||||
)
|
||||
INPUT_AGE = (
|
||||
"Enter your age:\n"
|
||||
"<i>Range: 13-120</i>"
|
||||
)
|
||||
INPUT_SEX = (
|
||||
"Enter your sex:\n"
|
||||
"<i>Options: Male or Female</i>"
|
||||
)
|
||||
INPUT_BIO = (
|
||||
"Enter your bio (enter /skip if you want to skip this step):\n"
|
||||
"<i>Maximum length: 100 characters</i>"
|
||||
)
|
||||
INPUT_BIO_SKIPPED = "✅ Sure. You can always fill it later."
|
||||
INPUT_LOCATION = "Enter your location in this format:\n<i>Format: country, city</i>\n<i>Example: Russia, Moscow</i>"
|
||||
INPUT_LOCATION = (
|
||||
"Enter your location in this format:\n"
|
||||
"<i>Format: country, city</i>\n"
|
||||
"<i>Example: Russia, Moscow</i>"
|
||||
)
|
||||
INPUT_CALLBACK = "✅ All right, your <b>{key}</b> is set to: <b>{value}</b>"
|
||||
VALIDATION_ERROR = "❌ Invalid input. Please try again."
|
||||
CANCEL_CHANGE = "<i>Enter /cancel to cancel change.</i>"
|
||||
|
||||
# User Profile
|
||||
PROFILE = (
|
||||
"<b>👤 Your profile:</b>\n\n"
|
||||
"\tUsername: <b>{username}</b>\n"
|
||||
@@ -106,9 +171,21 @@ PROFILE = (
|
||||
"\tDate joined: <b>{date_joined} UTC</b>\n"
|
||||
)
|
||||
NOT_SET = "<i>Not set</i>"
|
||||
EDIT_USERNAME = "Enter your username:\n<i>Allowed characters: a-z, A-Z, 0-9, _</i>\n<i>Length: 5-20 characters</i>"
|
||||
EDIT_BIO = "Enter your bio (enter /skip if you want to set it to None):\n<i>Maximum length: 100 characters</i>"
|
||||
PROFILE_UPDATED = "✅ Profile {key} updated\n\t<i>Old value: {old_value}</i>\n\t<i>New value: {new_value}</i>"
|
||||
EDIT_USERNAME = (
|
||||
"Enter your username:\n"
|
||||
"<i>Allowed characters: a-z, A-Z, 0-9, _</i>\n"
|
||||
"<i>Length: 5-20 characters</i>"
|
||||
)
|
||||
EDIT_BIO = (
|
||||
"Enter your bio (enter /skip if you want to set it to None):\n"
|
||||
"<i>Maximum length: 100 characters</i>"
|
||||
)
|
||||
PROFILE_UPDATED = (
|
||||
"✅ Profile {key} updated\n"
|
||||
"\t<i>Old value: {old_value}</i>\n"
|
||||
"\t<i>New value: {new_value}</i>"
|
||||
)
|
||||
CHANGE_CANCELED = "❌ Change canceled"
|
||||
|
||||
PROCCESSING = "⌛️ Processing..."
|
||||
# Processing
|
||||
PROCESSING = "⌛️ Processing..."
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
__all__ = ("throttling",)
|
||||
|
||||
from app.middlewares import throttling
|
||||
@@ -243,7 +243,7 @@ class Note(Base):
|
||||
def get_note_text(self):
|
||||
return messages.NOTE_DETAIL.format(
|
||||
file_name=self.file_name,
|
||||
file_type=self.file_type,
|
||||
file_type=self.file_type.capitalize(),
|
||||
public="Yes" if self.public else "No",
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user