How to call method without go to ConversationHandler in python-telegram-bot

How can I fix this problem? I get information from the user, for example, email address, but if that address is wrong, I show an error message to the user, and I want the user to redirect to get the input email address again and show to the user please enter the email address again, or in this code, I want to rerun gender method after user enter wrong enter email address but how can I call gender method from email method? The output is user should type something that ConversationHandler trigger and run the gender method to get the email address again

import re
 
from telegram import __version__ as TG_VER
 
try:
    from telegram import __version_info__
except ImportError:
    __version_info__ = (0, 0, 0, 0, 0)
 
if __version_info__ < (20, 0, 0, "alpha", 1):
    raise RuntimeError(
        f"This example is not compatible with your current PTB version {TG_VER}. To view the "
        f"{TG_VER} version of this example, "
        f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
    )
from telegram import ReplyKeyboardMarkup, ReplyKeyboardRemove, Update
from telegram.ext import (
    Application,
    CommandHandler,
    ContextTypes,
    ConversationHandler,
    MessageHandler,
    filters,
)
 
GENDER, EMAIL = range(2)
 
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
    reply_keyboard = [["Boy", "Girl", "Other"]]
    await update.message.reply_text(
        "Hi! My name is Professor Bot. I will hold a conversation with you. "
        "Are you a boy or a girl?",
        reply_markup=ReplyKeyboardMarkup(
            reply_keyboard, one_time_keyboard=True, input_field_placeholder="Boy or Girl?"
        ),
    )
    return GENDER
 
async def gender(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
    user = update.message.from_user
    await update.message.reply_text(
        "Please Enter your email:",
        reply_markup=ReplyKeyboardRemove(),
    )
 
    return EMAIL
 
async def email(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
    if update.message.text != "" and re.match(r'([A-Za-z0-9]+[.-_])*[A-Za-z0-9]+@[A-Za-z0-9-]+(.[A-Z|a-z]{2,})+', update.message.text):
        await update.message.reply_text(
            "Thanks for your registration",
            reply_markup=ReplyKeyboardRemove(),
        )
    else:
        await update.message.reply_text(
            "Your Email address was wrong!",
            reply_markup=ReplyKeyboardRemove(),
        )
        return GENDER
 
    return ConversationHandler.END
 
async def cancel(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
    await update.message.reply_text(
        "Bye! I hope we can talk again some day.", reply_markup=ReplyKeyboardRemove()
    )
    return ConversationHandler.END
 
def main() -> None:
    application = Application.builder().token("***************").build()
 
    # Add conversation handler with the states GENDER, PHOTO, LOCATION and BIO
    conv_handler = ConversationHandler(
        entry_points=[CommandHandler("start", start)],
        states={
            GENDER: [MessageHandler(filters.TEXT, gender)],
            EMAIL: [MessageHandler(filters.TEXT & ~filters.COMMAND, email)],
        },
        fallbacks=[CommandHandler("cancel", cancel)],
    )
 
    application.add_handler(conv_handler)
 
    # Run the bot until the user presses Ctrl-C
    application.run_polling()
 
 
if __name__ == "__main__":
    main()

I want show to user your Email address was wrong! then Please Enter your email: actually, I want to rerun gender method without waiting for user input something or trigger ConversationHandler inside the method

I need something like that for another where. Suppose I want to control the user’s state from the database and save steps in the database, so I need to go up and down in conversation, and all thing happens in one method. see this structure

async def register(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:

if user.user_status == 'start':

    if user.step == 0:
        //Show Accpet rules
        // if it accepet
            //go to step 1
    elif user.step == 1:
        //get name and family
        //goes to step 2
    elif user.step == 2:
        // check name and family
            // if it was correct
                // save in DB
                // get mobile number
            // if it was not correct
                // show error message 
                // back to step 1 and ask again name and family
    elif user.step == 3:
        // check mobile number 
            // if it was correct
                    // save in DB
                    //get email
            // if it was not correct
                    //show error message 
                    // back to step 2 and ask again mobile number
        // get email
        ....
    elif user.step == 4:
        ...
    elif user.step == 5:

        await update.message.reply_text(
                "you successfull register",
                reply_markup=await _reply_keyboard('GoHome'),parse_mode="HTML"
        )

return Register

Update:

I make a real example to show my mind and my problem. user should enter something until ConversationHandler trigger and it’s a big problem try this code:

import re

from telegram import __version__ as TG_VER

try:
    from telegram import __version_info__
except ImportError:
    __version_info__ = (0, 0, 0, 0, 0)

if __version_info__ < (20, 0, 0, "alpha", 1):
    raise RuntimeError(
        f"This example is not compatible with your current PTB version {TG_VER}. To view the "
        f"{TG_VER} version of this example, "
        f"visit https://docs.python-telegram-bot.org/en/v{TG_VER}/examples.html"
    )
from telegram import ReplyKeyboardMarkup, ReplyKeyboardRemove, Update
from telegram.ext import (
    Application,
    CommandHandler,
    ContextTypes,
    ConversationHandler,
    MessageHandler,
    filters,
)
step = 0
prev_step = 0
START,RULES,STEPS = range(3)

async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
    reply_keyboard = [["Yes", "No"]]
    await update.message.reply_text(
        "Hi! My name is Professor Bot. I will hold a conversation with you. "
        "Are you accept rules?",
        reply_markup=ReplyKeyboardMarkup(
            reply_keyboard, one_time_keyboard=True, input_field_placeholder="Yes or No?"
        ),
    )
    return STEPS

async def steps(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
    global step
    global prev_step

    if step == 0:
        print(step,prev_step)
        if update.message.text == "Yes" or prev_step == 1:
            step=1
            prev_step=0
            await update.message.reply_text(
                "Please enter your email address:",
                reply_markup=ReplyKeyboardRemove(),
            )
        else:
            await update.message.reply_text(
                "You should accept rules to continue!",
                reply_markup=ReplyKeyboardRemove(),
            )
            return START

    elif step == 1:
        prev_step = 1
        if update.message.text != "" and re.match(r'([A-Za-z0-9]+[.-_])*[A-Za-z0-9]+@[A-Za-z0-9-]+(.[A-Z|a-z]{2,})+', update.message.text):
            await update.message.reply_text(
                "Please enter your name:",
                reply_markup=ReplyKeyboardRemove(),
            )
            step = 2
        else:
            step = 0
            await update.message.reply_text(
                "Your Email address was wrong!",
                reply_markup=ReplyKeyboardRemove(),
            )

    return STEPS

async def cancel(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
    await update.message.reply_text(
        "Bye! I hope we can talk again some day.", reply_markup=ReplyKeyboardRemove()
    )
    return ConversationHandler.END

def main() -> None:
    application = Application.builder().token("*****").build()

    # Add conversation handler with the states GENDER, PHOTO, LOCATION and BIO
    conv_handler = ConversationHandler(
        entry_points=[CommandHandler("start", start)],
        states={
            START: [MessageHandler(filters.TEXT, start)],
            RULES: [MessageHandler(filters.TEXT, steps)],
            STEPS: [MessageHandler(filters.TEXT & ~filters.COMMAND, steps)],
        },
        fallbacks=[CommandHandler("cancel", cancel)],
    )

    application.add_handler(conv_handler)

    # Run the bot until the user presses Ctrl-C
    application.run_polling()


if __name__ == "__main__":
    main()

Leave a Comment