I am creating a python telegram bot. I have a series of operation to get and store a geographical location. I ask the user to assign a custom name to the chosen location, therefore I need to get a string through the MessageHandler(filter.TEXT,...). this task, of asking for a custom name, should run just once. After that, I want to exit theConversationHandler environment, so that I can assign new handlers for new input.
Thanks in advance for the help!
from telegram.ext import MessageHandler, filters, CommandHandler, ConversationHandler
from modules.weatherforecast.handlers.request_location_message import request_location_message, location_storage
from utilities.get_location import get_location
from modules.start.handlers.start_menu import start_menu
LOCATION, LOCATION_ACQUIRED, LOCATION_OUT_DOMAIN = range(3)
async def get_location(update: Update, context: CallbackContext, coord_to_check=None, country_to_check=None):
"""
This function handles the case when a user share their location. Optionally, it is possible to check if
the coords fall within a specific domain.
:param host: MySQL server host.
:param user: MySQL user.
:param passwd: MySQL password.
:param db: MySQL database name.
:param coord_to_check (list): List with [minlat, maxlat, minlon, maxlon] of the region to check
:param country_to_check (str): Name of the country/region to check.
:return (list): Instance of the class Location with Lat and Lon as attributes
"""
print("Get new location from user")
# user_obj = context.user_data.get('user')
# user_id = user_obj.telegramid
lat = update.message.location.latitude
lon = update.message.location.longitude
lat = np.round(lat, decimals=2)
lon = np.round(lon, decimals=2)
print('Location received')
if coord_to_check != None:
if lat > coord_to_check[0] or lat < coord_to_check[1] or lon > coord_to_check[2] or lon < coord_to_check[3]:
print(f'loc outside of {country_to_check}')
# If the location is outside the domain, return the message
await context.bot.send_message(chat_id=update.effective_chat.id,
text=f"Your location is outside of {country_to_check}, so we cannot provide you with a weather forecast. Please share a location within {country_to_check} to be able to receive a weather forecast.")
return LOCATION_OUT_DOMAIN
else:
context.user_data['location'] = create_location_obj(lat, lon)
"""Display the location's name request message"""
print("Location's name request message")
text = 'Type a name for the location that you just shared.'
await update.message.reply_text(text)
return LOCATION_ACQUIRED
async def request_location_message(update, context):
"""Display the request location message"""
print('Location request message')
text = 'Please share your location.'
await update.message.reply_text(text)
return LOCATION
def location_storage(update, context) -> int:
"""Display the location's name request message"""
loc_name_from_user = update.message.text
loc_obj = context.user_data.get('location')
user_obj = context.user_data.get('user')
# Add new attributes to the Locayion instance
loc_obj.name = loc_name_from_user
loc_obj.userid = user_obj.id
# SQL coordinates
host=
user=
passwd=
db=
loc_dict = {'UserId' : loc_obj.userid,
'Name' : loc_obj.name,
'Lat' : loc_obj.lat,
'Lon' : loc_obj.lon}
add_record_SQL(host, user, passwd, db, table_name='UserLocations', data=loc_dict)
print('New location stored in SQL')
return ConversationHandler.END
def cancel(update, context) -> int:
print('i am in cancel')
return ConversationHandler.END
def init(application):
conv_handler = ConversationHandler(
entry_points = [MessageHandler(filters.Regex('^Weather Forecast \u26c5\ufe0f$'), request_location_message)],
states = {LOCATION: [MessageHandler(filters.LOCATION, get_location)],
LOCATION_ACQUIRED: [MessageHandler(filters.TEXT & ~filters.COMMAND, location_storage)],
},
fallbacks = [CommandHandler('cancel', cancel)]
)
# application.add_handler(MessageHandler(filters.Regex('^Weather Forecast \u26c5\ufe0f$'), request_location_message))
application.add_handler(conv_handler)
if __name__ == '__main__':
print('STARTING BOT...')
application = Application.builder().token(mytoken).build()
# Init modules
start.init(application)
weatherforecast.init(application)
# weatherforecast.init(application)
#mymodule.init(application)
# mymodule1.init(application)
# mymodule2.init(application)
# mymodule3.init(application)
print('POLLING...')
application.run_polling(allowed_updates=Update.ALL_TYPES)
However, despite I set result ConversationHandler.END in my last function, I can never get out of the conversation. If the user type again something on the keybord, a new location record is created, and it is not what I want.