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 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()
2
Answers
I find a way I don't it is the correct way or is standard, but it works:
Modify your
email
function in the if clause when the user didn’t provide a valid email address. I would suggestWith this you can return to the same state in which you were:
return EMAIL
to enter the function again.In case of a successful answer,
return ConversationHandler.END