1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
|
#!/usr/bin/env python
# pylint: disable=unused-argument
# This program is dedicated to the public domain under the CC0 license.
"""
First, a few callback functions are defined. Then, those functions are passed to
the Application and registered at their respective places.
Then, the bot is started and runs until we press Ctrl-C on the command line.
Usage:
Example of a bot-user conversation using ConversationHandler.
Send /start to initiate the conversation.
Press Ctrl-C on the command line or send a signal to the process to stop the
bot.
"""
import logging
from telegram import ReplyKeyboardMarkup, ReplyKeyboardRemove, Update
from telegram.ext import (
Application,
CommandHandler,
ContextTypes,
ConversationHandler,
MessageHandler,
filters,
)
# Enable logging
logging.basicConfig(
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
)
# set higher logging level for httpx to avoid all GET and POST requests being logged
logging.getLogger("httpx").setLevel(logging.WARNING)
logger = logging.getLogger(__name__)
GENDER, PHOTO, LOCATION, BIO = range(4)
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
"""Starts the conversation and asks the user about their gender."""
reply_keyboard = [["Boy", "Girl", "Other"]]
await update.message.reply_text(
"Hi! My name is Professor Bot. I will hold a conversation with you. "
"Send /cancel to stop talking to me.\n\n"
"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:
"""Stores the selected gender and asks for a photo."""
user = update.message.from_user
logger.info("Gender of %s: %s", user.first_name, update.message.text)
await update.message.reply_text(
"I see! Please send me a photo of yourself, "
"so I know what you look like, or send /skip if you don't want to.",
reply_markup=ReplyKeyboardRemove(),
)
return PHOTO
async def photo(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
"""Stores the photo and asks for a location."""
user = update.message.from_user
photo_file = await update.message.photo[-1].get_file()
await photo_file.download_to_drive("user_photo.jpg")
logger.info("Photo of %s: %s", user.first_name, "user_photo.jpg")
await update.message.reply_text(
"Gorgeous! Now, send me your location please, or send /skip if you don't want to."
)
return LOCATION
async def skip_photo(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
"""Skips the photo and asks for a location."""
user = update.message.from_user
logger.info("User %s did not send a photo.", user.first_name)
await update.message.reply_text(
"I bet you look great! Now, send me your location please, or send /skip."
)
return LOCATION
async def location(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
"""Stores the location and asks for some info about the user."""
user = update.message.from_user
user_location = update.message.location
logger.info(
"Location of %s: %f / %f", user.first_name, user_location.latitude, user_location.longitude
)
await update.message.reply_text(
"Maybe I can visit you sometime! At last, tell me something about yourself."
)
return BIO
async def skip_location(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
"""Skips the location and asks for info about the user."""
user = update.message.from_user
logger.info("User %s did not send a location.", user.first_name)
await update.message.reply_text(
"You seem a bit paranoid! At last, tell me something about yourself."
)
return BIO
async def bio(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
"""Stores the info about the user and ends the conversation."""
user = update.message.from_user
logger.info("Bio of %s: %s", user.first_name, update.message.text)
await update.message.reply_text("Thank you! I hope we can talk again some day.")
return ConversationHandler.END
async def cancel(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
"""Cancels and ends the conversation."""
user = update.message.from_user
logger.info("User %s canceled the conversation.", user.first_name)
await update.message.reply_text(
"Bye! I hope we can talk again some day.", reply_markup=ReplyKeyboardRemove()
)
return ConversationHandler.END
def main() -> None:
"""Run the bot."""
# Create the Application and pass it your bot's token.
application = Application.builder().token("TOKEN").build()
# Add conversation handler with the states GENDER, PHOTO, LOCATION and BIO
conv_handler = ConversationHandler(
entry_points=[CommandHandler("start", start)],
states={
# Use case-insensitive regex to accept gender input regardless of letter casing,
# e.g., "boy", "BOY", "Girl", etc., will all be matched
GENDER: [MessageHandler(filters.Regex("(?i)^(Boy|Girl|Other)$"), gender)],
PHOTO: [MessageHandler(filters.PHOTO, photo), CommandHandler("skip", skip_photo)],
LOCATION: [
MessageHandler(filters.LOCATION, location),
CommandHandler("skip", skip_location),
],
BIO: [MessageHandler(filters.TEXT & ~filters.COMMAND, bio)],
},
fallbacks=[CommandHandler("cancel", cancel)],
)
application.add_handler(conv_handler)
# Run the bot until the user presses Ctrl-C
application.run_polling(allowed_updates=Update.ALL_TYPES)
if __name__ == "__main__":
main()
|