ConversationHandler ignoring .END command

25 Views Asked by At

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.

0

There are 0 best solutions below