How to change a previous Inlinekeyboard message from a normal message - python

In my bot, the user is supposed to interact mostly through Inlinekeyboard messages.
So, if the user writes some 'regular' message or sends something, I must somehow change the last Inlinekeyboard message to continue the process or give him some message.
See the picture below:
The user wrote some message but I had to create a new Inlinekeyboard button with the new message because I couldn't find a way to get the message_id of the previous 'Welcome' button and change it.
My code:
HELP = range(1)
def start(bot, update):
keyboard = [
[InlineKeyboardButton('Help', callback_data='help')]
]
# Create initial message:
message = 'Welcome.'
update.message.reply_text(message, reply_markup=InlineKeyboardMarkup(keyboard))
def help(bot, update):
keyboard = [
[InlineKeyboardButton('Help', callback_data='help')]
]
bot.edit_message_text(
text='Help ... help..',
chat_id=update.callback_query.message.chat_id,
message_id=update.callback_query.message.message_id,
reply_markup=InlineKeyboardMarkup(keyboard)
)
bot.answer_callback_query(update.callback_query.id, text='')
def unknown(bot, update):
message = 'Please press the Help button for more instructions.'
keyboard = [
[InlineKeyboardButton('Help', callback_data='help')]
]
update.message.reply_text(message, reply_markup=InlineKeyboardMarkup(keyboard))
# Create the EventHandler and pass it your bot's token.
updater = Updater(token=config.TELEGRAM_API_TOKEN)
# Get the dispatcher to register handlers:
dispatcher = updater.dispatcher
dispatcher.add_handler(CommandHandler('start', start))
dispatcher.add_handler(CallbackQueryHandler(help, pattern='help'))
dispatcher.add_handler(MessageHandler(Filters.all, unknown))
updater.start_polling()
updater.idle()
Best Regards.
Kleyson Rios.

If you want to edit the previous messages that the bot has sent, you need to store their message_id (which you already know).
So you can simply do this:
sent_message = update.message.reply_text(
message,
reply_markup=InlineKeyboardMarkup(keyboard)
)
And then you can access it like sent_message.message_id
Now for the variable sent_message, you can make it global or create a separate file to handle these variables, or at larger scale, you can store it in a database.

Related

How to get info from reply on specific message - Telegram Bot

Let's say I have this command handler:
#bot.message_handler(commands=['setalarm'])
def setalarmcmd(message):
alarmMessage = "Let's start with setting up alarm.\n\n" \
"First of all, provide the pair you want to observe."
bot.send_message(message.chat.id, alarmMessage)
I want to set some action when user click /setalarm command and replies on this message.
Actually, I know how to do that, but I already have handler on provided text:
#bot.message_handler(content_types=['text'])
def getpairfuncmessage(message):
userMessage = message.text.strip().upper()
pair = getPairApi(userMessage)
if not pair:
return bot.send_message(message.chat.id, "Nah, not that, try something else.")
pairResult = printPairResult(pair)
bot.send_message(message.chat.id, pairResult, parse_mode='html')
And that's the problem. By providing message, user triggers this action, but I want to set another one, after /setalarm command. Is this possible?
Here is how you can do this:
#bot.message_handler(commands=['setalarm'])
def setalarmcmd(message):
alarmMessage = "Let's start with setting up alarm.\n\n" \
"First of all, provide the pair you want to observe."
msg = bot.send_message(message.chat.id, alarmMessage)
bot.register_next_step_handler(msg, setalarmcryptopair)
def setalarmcryptopair(pair):
print(pair.text)
Using send_message and register_next_step_handler to go to next function.

How can I continue a nested conversation in a separate file

I am not a professional programmer but I'm trying to build a python-telegram-bot for work using ConversationHandlers. Basically, I offer users a menu of options, summarized as:
Complete Survey
EXIT
If "Complete Survey" is selected, the bot then asks for the user ID. Depending on the user ID I assign the user 1 of 30+ different surveys (I'm trying to use child conversations). Over time this list of surveys will grow and each survey has unique questions and steps to it.
Given the number of surveys, I thought of managing each survey as a child conversation with its own ConversationHandler, and running it from a separate file/module (to keep things dynamic and not have one HUGE file with n+ variables to consider).
The thing is, how can I continue the child conversation from a separate file? Is there another way to approach this? I understand that the bot is still running from the main file and checking for updates. I would like to run each survey and, once finished, return to the INITIAL bot menu (parent conversation).
I found this previous discussion but my knowledge barely goes beyond the python-telegram-bot examples so I'm having a hard time following along: https://github.com/python-telegram-bot/python-telegram-bot/issues/2388
Here is an example summarized code of what I'm trying to do:
main_file.py
from telegram import ReplyKeyboardMarkup, ReplyKeyboardRemove, InlineKeyboardMarkup, InlineKeyboardButton, Update, KeyboardButton, Bot, InputMediaPhoto
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters, ConversationHandler, CallbackQueryHandler, CallbackContext
import surveys # this file contains each survey as a function with its own ConversationHandler
token = ''
MENU, USER, CHAT_ID, USER_ID, FINISHED = map(chr, range(1,6))
END = ConversationHandler.END
def start(update: Update, context: CallbackContext) -> int:
"""Initialize the bot"""
context.user_data[CHAT_ID] = update.message.chat_id
text = 'Select an option:'
reply_keyboard = [
['Complete Survey'],
['EXIT'],
]
context.bot.send_message(
context.user_data[CHAT_ID],
text=text,
reply_markup=ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True)
)
return MENU
def exit(update:Update, context:CallbackContext) -> None:
"""Exit from the main menu"""
context.bot.send_message(
context.user_data[CHAT_ID],
text='OK bye!',
reply_markup=ReplyKeyboardRemove()
)
return END
def abrupt_exit(update:Update, context:CallbackContext) -> None:
"""Exit the main conversation to enter the survey conversation"""
return END
def survey_start(update:Update, context:CallbackContext) -> None:
"""Asks for the user_id in order to determine which survey to offer"""
text = 'Please type in your company ID'
context.bot.send_message(
context.user_data[CHAT_ID],
text=text,
reply_markup=ReplyKeyboardRemove()
)
return USER
def survey_select(update:Update, context:CallbackContext) -> None:
"""Search database to find next survey to complete"""
user = str(update.message.text)
chat_id = context.user_data[CHAT_ID]
context.user_data[USER_ID] = user
"""Search database with user_id and return survey to complete"""
survey = 'survey_a' # this value is obtained from the database
runSurvey = getattr(surveys, survey) # I used getattr to load functions in a different module
runSurvey(Update, CallbackContext, user, chat_id, token)
return FINISHED
def main() -> None:
updater = Updater(token, use_context=True)
# Get the dispatcher to register handlers
dispatcher = updater.dispatcher
# Survey conversation
survey_handler = ConversationHandler(
entry_points=[
MessageHandler(Filters.regex('^Complete Survey$'), survey_start),
],
states={
USER: [
MessageHandler(Filters.text, survey_select),
],
FINISHED: [
# I'm guessing here I should add something to exit the survey ConversationHandler
],
},
fallbacks=[
CommandHandler('stop', exit),
],
)
# Initial conversation
conv_handler=ConversationHandler(
entry_points=[
CommandHandler('start', start),
],
states={
MENU: [
MessageHandler(Filters.regex('^Complete Survey$'), abrupt_exit),
MessageHandler(Filters.regex('^EXIT$'), exit),
],
},
allow_reentry=True,
fallbacks=[
CommandHandler('stop', exit),
],
)
dispatcher.add_handler(conv_handler, group=0) # I used separate groups because I tried ending
dispatcher.add_handler(survey_handler, group=1) # the initial conversation and starting the other
# Start the Bot
updater.start_polling()
updater.idle()
if __name__ == '__main__':
main()
surveys.py This is where each survey is with its own conversation and functions to call. Basically I enter survey_A (previously selected) and am trying to use it as the main()
from telegram import ReplyKeyboardMarkup, ReplyKeyboardRemove, InlineKeyboardMarkup, InlineKeyboardButton, Update, \
KeyboardButton, Bot, InputMediaPhoto
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters, ConversationHandler, CallbackQueryHandler, \
CallbackContext
NEXT_QUESTION, LAST_QUESTION, CHAT_ID = map(chr, range(1,4))
END = ConversationHandler.END
def exit(update:Update, context:CallbackContext) -> None:
"""Exit from the main menu"""
context.bot.send_message(
context.user_data[CHAT_ID],
text='OK bye!',
reply_markup=ReplyKeyboardRemove()
)
return END
def first_q(update:Update, context:CallbackContext, chat_id:str) -> None:
"""First survey_A question"""
context.bot.send_message(
chat_id,
text='What is your name?',
reply_markup=ReplyKeyboardRemove()
)
return NEXT_QUESTION
def last_q(update: Update, context: CallbackContext) -> None:
"""Last survey_A question"""
update.message.reply_text(
'How old are you?', reply_markup=ReplyKeyboardRemove()
)
return LAST_QUESTION
def survey_a(update:Update, context:CallbackContext, user:str, chat_id: str, token:str) -> None:
"""This function acts like the main() for the survey A conversation"""
print(f'{user} will now respond survey_a')
CHAT_ID = chat_id # identify the chat_id to use
updater = Updater(token, use_context=True) # here I thought of calling the Updater once more
survey_a_handler = ConversationHandler(
entry_points=[
MessageHandler(Filters.text, first_q),
],
states={
NEXT_QUESTION: [
MessageHandler(Filters.text, last_q),
],
LAST_QUESTION: [
MessageHandler(Filters.text, exit),
],
},
allow_reentry=True,
fallbacks=[
CommandHandler('stop', exit),
],
)
updater.dispatcher.add_handler(survey_a_handler, group=0) # I only want to add the corresponding
# survey conversation handler
first_q(Update, CallbackContext, CHAT_ID)
I run the code and it breaks at surveys.py line 23, in first_q:
context.bot.send_message(
AttributeError: 'property' object has no attribute 'send_message'
I assume my logic with the conversation handler is way off.
I appreciate any help
I have been developing telegram bots for about a year now, and I hope the best approach is to structure your project first. Let me explain that all in detail.
"Foldering"
Folder structure
Basically, all the code is in the src folder of the project. Inside the src folder there is another sub-folder called components which includes all the different sections of your bot you want to work on (i.e your quiz_1, quiz_2, ...) and main.py file which includes the 'core' of the bot. However in the root directory of the project (which is just your project folder) you can see bot.py file which serves just as a runner file. So nothing more in there except just:
import src.main from main
if '__name__' == '__main__':
main()
Tips
So regarding your questionnaire:
I would recommend using just strings as keys for the states instead of mapping them to random values. Basically you can do just like "MAIN_MENU", "STATE_ONE" , "STATE_TWO" and so on, but be sure to return the same string in the callback function!
The overall logic of the PTB library is like:
Telegram API server -> PTB Updater() class -> Dispatcher() (which is updater.dispatcher in your code) -> Handlers -> callback function -> <- user.
The reason arrows point to user and back to callback function is because there is an interaction of your bot's logic and user, so that user's response goes back to your callback function code.
I recommend not choosing callback function names as like 'first_question' or 'second_question'. Instead name it like get_question() use that function to retrieve question data from other source so that it can be dynamic. So for example, you will have a dictionary of different questions with keys of question number - simple, right? And then you will write a function that will send user a question according to its state and picking the right question with the right key from the dictionary. By this you can add more questions to your dictionary and no need to change the code in the function because it will be dynamic (as long as you write the correct function that will work).
In your main.py file have only one main() function which will hold the Updater() with the given token, because you cannot have more than one Updater() with the same token. It's like one bot can be accessed by only and only one app that is polling at a time. Polling - visit here.
🎉 Great news!
To support your bot development and follow the structured project creation, I have created a repo on GitHub that holds almost the same project structure as I tried to explain to you today. Feel free to check it out, clone it and play around. Just add your token to .env file and run the bot.
More resources
Check out these projects as well:
https://github.com/ez-developers/traderbot/tree/master/bot
https://github.com/ez-developers/equip.uz/tree/main/bot
As you will see in there main.py contains all the handlers and src folder contains all the different 'components' which are more of a like different parts of the bot.
If you need any help, I am here and more than happy to answer any of your questions.

How to trigger a conversation handler with the bot reply? [Telegram Bot] [Python] [python-telegram-bot]

The logic is the following:
With the /start command the bot shows the Main Menu with buttons (each button represents a file the user wants to get access to);
When any button is pressed, the conversation starts where the bot asks for a gmail address;
The user sends their gmail address, the bot checks it, if the address format is correct then the bot grants the permission to view the file and posts the link to the chat.
I used these examples as my starting point:
https://github.com/python-telegram-bot/python-telegram-bot/blob/master/examples/conversationbot.py
https://github.com/python-telegram-bot/python-telegram-bot/blob/master/examples/conversationbot2.py
My code is this one:
from telegram import (
Bot,
Update,
InlineKeyboardMarkup,
InlineKeyboardButton,
)
from telegram.ext import (
Updater,
CommandHandler,
MessageHandler,
Filters,
CallbackContext,
CallbackQueryHandler,
ConversationHandler,
)
def startCommand(update: Update, context: CallbackContext):
keyboardMarkup = InlineKeyboardMarkup(
[[InlineKeyboardButton('Share File 1', callback_data='sharingFile1')]]
)
update.message.reply_text(f'Howdy, {update.effective_user.first_name}.\nThis is the Main Menu.',
reply_markup=keyboardMarkup)
def convGetGMailAddr(update: Update, context: CallbackContext):
update.message.reply_text('Waiting for your gmail address.\n\nSend /end and I\'ll stop waiting.')
return convEmailAddr
def convMismatch(update: Update, context: CallbackContext):
text = f"""Sorry, I don't understand this gmail address.
Please, send me your gmail address again.\n\nSend /end and I\'ll stop waiting.
"""
update.message.reply_text(text)
return convEmailAddr
def convGiveLink(update: Update, context: CallbackContext):
link = 'https://docs.google.com/spreadsheets/d/1ZP1xZ0WaH8w2yaQTSx99gafNZWawQabcdVW5DSngavQ'
update.message.reply_text(f'Thank you! Here\'s your link to the shared file:\n{link}')
return ConversationHandler.END
def convEnd(update: Update, context: CallbackContext):
update.message.reply_text('I\'ve stopped waiting.\n\nSend /start to go to the Main Menu.')
return ConversationHandler.END
def sharingFileHandler(update: Update, context: CallbackContext):
if update.callback_query.data == 'sharingFile1':
update.callback_query.edit_message_text(
update.effective_message.text,
reply_markup=InlineKeyboardMarkup([])
)
conv_sharing = ConversationHandler(
entry_points=[MessageHandler(Filters.regex('.*[File 1]*.*'), convGetGMailAddr)],
states={
convEmailAddr: [
MessageHandler(~Filters.regex('.*#gmail.com$') & ~Filters.command, convMismatch),
MessageHandler(Filters.regex('.*#gmail.com$'), convGiveLink),
],
},
fallbacks=[CommandHandler('end', convEnd)],
)
disp.add_handler(conv_sharing)
bot.send_message(update.effective_chat.id, 'I\'ll share the File 1 with you.')
bot_token = 'abcd1234'
bot = Bot(bot_token)
updater = Updater(bot_token, use_context=True)
convEmailAddr = ''
disp = updater.dispatcher
disp.add_handler(CommandHandler('start', startCommand))
disp.add_handler(CallbackQueryHandler(sharingFileHandler))
updater.start_polling(drop_pending_updates=True)
updater.idle()
The issue is that the bot doesn't read it's own reply in the function sharingFileHandler to start the conversation handler. The entry point of the conversation is posting the string "File 1" and when I send something like "asdklhasdlkh file 1 asdaskldha" then everything works fine.
Another question is is it possible for the bot to listen to email addresses only inside of the conversation? Right now the function convGetGMailAddr starts at any moment.
Update 1 (2021-10-20)
Based on the CallMeStag's answer I changed my code.
Deleted the function convGetGMailAddr and modified the function sharingFileHandler:
def sharingFileHandler(update: Update, context: CallbackContext):
if update.callback_query.data == 'sharingFile1':
update.callback_query.edit_message_text(
update.effective_message.text,
reply_markup=InlineKeyboardMarkup([])
)
text = f"""I\'ll share the File 1 with you to your Google account.
Please, send me your gmail address.\n\nSend /end and I\'ll stop waiting."""
bot.send_message(update.effective_chat.id, text)
return convEmailAddr
bot_token = '1234abcd'
bot = Bot(bot_token)
updater = Updater(bot_token, use_context=True)
convEmailAddr = ''
disp = updater.dispatcher
disp.add_handler(CommandHandler('start', startCommand))
conv_sharing = ConversationHandler(
entry_points=[CallbackQueryHandler(sharingFileHandler)],
states={
convEmailAddr: [
MessageHandler(~Filters.regex('.*#gmail.com$') & ~Filters.command, convMismatch),
MessageHandler(Filters.regex('.*#gmail.com$'), convGiveLink),
],
},
fallbacks=[CommandHandler('end', convEnd)],
)
disp.add_handler(conv_sharing)
updater.start_polling(drop_pending_updates=True)
updater.idle()
Now my bot does exactly what I want and it stopped doing what I wanted it to stop doing. 🙂
Thank you, CallMeStag!
You're building a new conversationhandler & adding it to the dispatcher every time sharingFileHandler is called. that's surely not what you want. You should instead build it only once and add it to the dispatcher also only once right where you add the other handlers (at the very end of your snippet).
You should then make CallbackQueryHandler(sharingFileHandler) the entry point of that conversation. this will automatically solve your second problem.
Disclaimer: I'm currently the maintainer of python-telegram-bot.

python telegrambot store chat id

I am wondering how I could store/read out a user chat ID to later send them messages.
Example would be, that the user is adding my telegram bot and sends him a message.
Later on in my program at some point, when a sepcific situation occurs, I want to send a message to the specific user.
For a simple example I have this code:
a=1
b=2
if a > b:
# at this point python should send a message to a user via telegram privat chat
else:
# send a different message
I know how to handle a response to a command sent by the user in the telegram chat, but not how to send a message to a user without receiving a command first. I think there fore I would need to have a way to store the users chat Id first to later refer to that Id when sending the message.
The point is I want to compile my program to .exe later on and send it to some friends and it should work for them as well.
It is very easy, just use a simple database.
MongoDB is the best choose in my opinion.
Create an account on it and follow this tutorial.
First get the user_id
userid1 = str(update.message.chat_id)
Then store it into the database
import pymongo
from pymongo import MongoClient
cluster = MongoClient("mongodb+srv://<user>:<password>#cluster0.uubct.mongodb.net/users?retryWrites=true&w=majority")
db = cluster["users"]
collection = db["users"]
results = collection.find({"_id": int(userid1)})
if results.count() == 0:
print("post")
post = {"_id": int(userid1)}
collection.insert_one(post)
else:
print("User already in the database!")
For getting it you need to use the find() method.
results = collection.find()
for result in results:
var1 = (result["_id"])
print(var1)
context.bot.send_message(chat_id=prova,
text = "Hi")
You can simply add the id in a list WHITOUT ANY THIRD PARTS PAKAGE
import telebot
TOKEN = ""
bot = telebot.TeleBot(TOKEN)
admin = # your chat id
users = []
#bot.message_handler(commands=['start'])
def start_message(msg):
bot.send_message(msg.chat.id, 'Welcome!')
if msg.chat.id not in users: # if the id isn't already in the users list
users.append(msg.chat.id)
#bot.message_handler(commands=['send_at_all']) # A way to use the list
def sendAtAll(msg):
if msg.chat.id == admin: # only if YOU start the command the message will be sent
for id in users: # for every user that has start the bot
bot.send_message(id, "I'm sending this message at all the users")
# If an user wants to stop the notifications...
#bot.message_handler(commands=['unsubscribe'])
def sendAtAll(msg):
del users[msg.chat.id]
bot.send_message(msg.chat.id, "If you want to receive the notification click /start")
# Every time you are going to restart the bot polling the content of the users list will be deleated so...
#bot.message_handler(commands=['save_user_list'])
def sendAtAll(msg):
if msg.chat.id == admin:
bot.send_message(admin, users)
# the list will be sent to your telegram chat, when you activate the bot you can add the list manually
bot.polling()
You can also create a class and save every chat id as an object
import telebot
from random import choice
TOKEN = ''
bot = telebot.TeleBot(TOKEN)
admin = # your chat id
users = []
class Userbot: # The class User is already in the pyTelegramBotAPI
def __init__(self, msg):
self.id = msg.chat.id
self.username = '#' + msg.from_user.username
def contestWinner(self):
text = f'Hi {self.username}, you have win!!!'
bot.send_message(self.id, text)
#bot.message_handler(commands=['start'])
def start(msg):
bot.send_message(msg.chat.id, 'Welcome!')
for el in users:
if msg.chat.id not in el.id:
users.append(Userbot(msg))
# you can't type 'if msg.chat.id not in users.id' because only the object inside the list can use the method id
#bot.message_handler(commands=['extract']) # another way to use the list
def extract(msg):
if msg.chat.id == admin:
winner = choice(users)
winner.contestWinner()
#bot.message_handler(commands=['unsubscribe'])
def sendAtAll(msg):
for el in users:
if msg.chat.id == el.id:
del users[el]
# only if the user inside the object is the same as the user that has sent the message the object will be deleated
bot.send_message(msg.chat.id, "If you want to receive the notification click /start")
#bot.message_handler(commands=['save_user_list'])
def sendAtAll(msg):
if msg.chat.id == admin:
bot.send_message(admin, users)
bot.polling()
Apologise for my terrible english

Save user input after certain message telegram bot

I am building some telegram bot on python (using this framework pyTelegramBotAPI). And I ran into the problem with user input. I need save user input(it can be any text) after certain bot's message. For example:
Bot: - Please describe your problem.
User: - Our computer doesn't work.
Then I need to save this text "Our computer doesn't work" to some variable and go to the next step.
Here's my code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import telebot
import constants
from telebot import types
bot = telebot.TeleBot(constants.token)
#bot.message_handler(commands=['start'])
def handle_start(message):
keyboard = types.InlineKeyboardMarkup()
callback_button = types.InlineKeyboardButton(text="Help me!", callback_data="start")
keyboard.add(callback_button)
bot.send_message(message.chat.id, "Welcome I am helper bot!", reply_markup=keyboard)
#bot.inline_handler(lambda query: len(query.query) > 0)
def query_text(query):
kb = types.InlineKeyboardMarkup()
kb.add(types.InlineKeyboardButton(text="Help me!", callback_data="start"))
results = []
single_msg = types.InlineQueryResultArticle(
id="1", title="Press me",
input_message_content=types.InputTextMessageContent(message_text="Welcome I am helper bot!"),
reply_markup=kb
)
results.append(single_msg)
bot.answer_inline_query(query.id, results)
#bot.callback_query_handler(func=lambda call: True)
def callback_inline(call):
if call.message:
if call.data == "start":
bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id, text="Please describe your problem.")
#here I need wait for user text response, save it and go to the next step
I have the idea with using message_id in statement, but still can't implement it. How I can solve this? Any ideas? Thank you.
This will help you
https://github.com/eternnoir/pyTelegramBotAPI/blob/master/examples/step_example.py
import telebot
import constants
from telebot import types
bot = telebot.TeleBot(constants.token)
#bot.message_handler(commands=['start'])
def start(message):
sent = bot.send_message(message.chat.id, 'Please describe your problem.')
bot.register_next_step_handler(sent, hello)
def hello(message):
open('problem.txt', 'w').write(message.chat.id + ' | ' + message.text + '||')
bot.send_message(message.chat.id, 'Thank you!')
bot.send_message(ADMIN_ID, message.chat.id + ' | ' + message.text)
bot.polling()
its not a python or even programming related question. its more like designing problem. but anyway.
the solution is keeping session for users. for example user send you:
Our computer doesn't work.
at first you create a session for this user(the identity should be a user id) then send him/her a proper message. when user send the next message at first you look at the user status and see if he/she has a session or not. if he/she has session you continue with second step. i develop a bot like this and used dictionary in order to store users sessions. but it make all thing little complicated.
You can use Forcereply.
Upon receiving a message with this object, Telegram clients will display a reply interface to the user (act as if the user has selected the bot‘s message and tapped ’Reply'). This can be extremely useful if you want to create user-friendly step-by-step interfaces without having to sacrifice privacy mode. https://core.telegram.org/bots/api#forcereply
i know how fix that. It took 3 years for solution.
Just look at my code and make your own. Thx
#bot.callback_query_handler(func=lambda call: True)
def callback_inline(call): #your call
UserID = str(call.message.chat.id)
if call.data == 'PhotoTEXT':
#bot.message_handler(content_types=['text'])
def SetTEXTonPHOTO(message): # THIS FUNCTION
sent = bot.send_message(message.chat.id,'send me text')
bot.register_next_step_handler(sent, TextONphoto)
def TextONphoto(message): #Thsi function add text on photo
im = Image.open('UserData/Files/photos/not_converted/'+UserID+'.jpg')
idraw = ImageDraw.Draw(im)
text = message.text
font = ImageFont.truetype("arial.ttf", size=18)
idraw.text((10, 10), text, font=font)
im.save('UserData/Files/photos/converted/'+UserID+'.jpg')
im.show()
SetTEXTonPHOTO(call.message) #just run your function
with open('UserData/Files/photos/converted/'+UserID+'.jpg', 'rb') as file:
bot.send_document(UserID,file)
I think i helped you friends <3
You should save the data in cache or database.

Categories

Resources