I'm having a problem with handling incoming messages. I have a main menu in my bot with one InlineKeyboardMarkup. When the button is pressed, the bot should wait for user input and then send a message. But in my case, it sends the message, then it waits for user input and then it sends again the message. And that's a big problem, because after the message it sends, it should go back to main menu.
I'm using pythonTelegramBotAPI (telebot)
That's the code:
#bot.callback_query_handler(func = lambda call: True)
def query_handler(call):
bot.answer_callback_query(callback_query_id = call.id, text = '')
cid = call.message.chat.id
mid = call.message.message_id
msg = call.message
if call.data == 'request':
bot.edit_message_text('Test - Answer to request', cid, mid, reply_markup = markup)
request_handler(msg)
################# Keyboard sections #################
#bot.message_handler()
def request_handler(msg):
if msg.content_type == 'text':
bot.send_message(msg.chat.id, 'Request accepted')
# and here the code to go back, that I didn't do yet
Perhaps this conversational bot example will help you to understand how to build dialog with user.
Correct answer
The decorator #bot.messge_handler() is used to tell to the function that it must be handle incoming messages. So, when there's a new message, the function will do the code inside it automatically. This means that the function must not be called manually as is not required. Calling the function will, in fact, run the code inside it, instead of initializing it and waiting for an input.
And here's a tip: if the user send a message, the function is automatically called. But what happens when the bot send a message? The function is also called, because it doesn't make difference about who sent the message. So, to avoid using the function also for bot messages, just put an if in like this:
if msg.from_user.is_bot == False:
# Here put what the function should do
The if, as you can see, check if the message is coming from the bot.
Related
I am developing a little bot in python with the library python-telegram-bot, and I am stucked with a little problem :
I have an InlineKeyboardButton with the parameter switch_inline_query_current_chat, so when the user click on it, a command is automatically written in its chat.
But, that command is preceded with the mention of the bot (with an #).
The problem is my bot isn't answering in that case, and I have no idea why..
Is there a solution to make the button do not preced the command with the mention of the bot ?
From #BotFather the groups are allowed and the privacy group is turned off.
Thank you a lot
Edit : This is the code for the CommandHandler :
def getEntry(update, context):
if not (is_allowed_user(update.message.from_user.username, 'getEntry')):
context.bot.send_message(chat_id=update.effective_chat.id,
text='Who the hell are you #' + update.message.from_user.username + ' ?')
return
search = ' '.join(context.args)
infos, err = get_infos_people(search)
if err is not None:
context.bot.send_message(chat_id=update.effective_chat.id, text=err)
return
context.bot.send_message(chat_id=update.effective_chat.id, text=beautify_infos(infos),
parse_mode=ParseMode.MARKDOWN, reply_markup=getMainKeyboard(infos))
get_handler = CommandHandler('get', getEntry, filters=~Filters.update.edited_message)
And this is the code for the buttons :
def getMainKeyboard(infos):
keyboard = [InlineKeyboardButton("modify",
switch_inline_query_current_chat="/get " + infos[0] + "<write here>")]]
return InlineKeyboardMarkup(keyboard)
Note: I'm no python-telegram-bot expert, but the issue/fix should be non-lib related
Your commandHandler() is defined as so:
get_handler = CommandHandler('get', getEntry, filters=~Filters.update.edited_message)
This links the /get command to the getEntry handler.
Issue
Since the command is only fired at /get, you'll need to add a second command with the name of the bot so it will register that command as-well;
get_handler = CommandHandler([ 'get', 'get#myBot' ], getEntry, filters=~Filters.update.edited_message)
The first argument (command) accepts both a str or a list as the docs shows
Had the same issue in some other library, don't think there is a 'cleaner' way of handeling this.
I'm using Twilio with Whatsapp, I want to take multiple inputs from users on Whatsapp but I am only able to get the first input.
My first input is usually "hello" from user
then my query
and the second input I want
```
#app.route("/allr", methods=['POST'])
def start():
phonestring = request.form["From"]
phonenumber = int(re.search(r'\d+', phonestring).group(0))
print(phonenumber)
resp = MessagingResponse()
msg1 = request.form.get('Body') #usually hello or something to initialize
l1 = (db.search(User.Phone == phonenumber))
if len(l1)!=0:
aj=l1[0]
print(aj['Preference'])
pref=aj['Preference']
print("Done")
resp.message("{} News".format(pref))
else:
resp.message("Which updates would you like?\n1.National\n2.Regional")
pref = request.form.get('Body') # I need input but I get it as hello(the input above)
print(pref)
resp.message("You selected: {}".format(pref))
Item3 = {'Phone': phonenumber, 'Preference': pref}
db.insert(Item3)
return str(resp)
```
Expected: Regional/National
What I get: Hello
Twilio developer evangelist here.
It appears that when you receive the user's first message that you are not storing anything in the database. So, when you receive their second message, you look up the user by phone number but still don't find anything.
Also, it sounds like you are expecting to receive more than one message within this piece of code. Each webhook request from Twilio corresponds to one incoming message. If you are looking for the response to the second message, it will be in a second webhook.
I have an Errbot function that sends a Slack card. How do I then add a reaction to the card instead of the original message(msg) that was received?
#botcmd
def example(self, msg):
self.send_card(title='Test',
body='test123',
thumbnail=' ',
image=' ',
link=' ',
color='green',
in_reply_to=msg)
self._bot.add_reaction(card_msg??, 'grey_question')
send_card does not return to you the message it sends which means you will have to do something to get the message info of the card you sent.
One option would be to trigger a callback for all messages in your plugin, inspect the message, and add your reaction there:
Another option could be to use the slack backend api call method to search for your message and add the reaction that way.
I would like to forward every updates from channels to my bot.
Is it Possible with ForwardMessagesRequest ?
I tried to use this Telethon example to build my personal code:
https://github.com/LonamiWebs/Telethon/wiki/Forwarding-messages
But i wasn't able to do it. And i don't know if it's possible to use that part of code inside a callback function. Someone can help me? Thank you
Ok, i'm really confused so let's go back.
In this code I just try to retrieve last messages from an user chat and forward them to my bot:
def callback(update):
source_chat_id = "here i put the user id"
source_hash = "here i put his access_hash"
source_chat = InputPeerUser(source_chat_id, source_hash)
total_count, messages, senders = client.get_message_history(
source_chat, limit=10)
for msg in reversed(messages):
print ("msg:", msg.id, msg)
msg = messages[0]
print ("msg id:", msg.id)
dest_chat = "here i tried to put the number of my bot ID"
result = client.invoke(ForwardMessagesRequest(from_peer=source_chat, id=[msg.id], random_id=[generate_random_long()], to_peer=dest_chat))
client.add_update_handler(callback)
The print was correct but i didn't receive anything to my bot chat.
I know that there will be a lot of errors so please be patient and sorry.
I try use python-telegram-bot
I do not understand how to handle InlineKeyboardButton correctly.
def start(bot, update):
currencies = [currency for currency in API().get_currencies()]
keyboard = [[InlineKeyboardButton("{}".format(c), callback_data='{}'.format(c))] for c in currencies]
reply_markup = InlineKeyboardMarkup(keyboard)
update.message.reply_text('Select the currency you want to exchange:', reply_markup=reply_markup)
updater.dispatcher.add_handler(CommandHandler('start', start))
Now, I need to process the selection by passing it to another function with the help of ChosenInlineResultHandler, but I do not understand how to do this.
You are using Inline Buttons and the query coming back is simply CallbackQuery but not InlineQuery, yes the names are a bit confusing by the Telegram Bot API.
You can use telegram.ext.CallbackQueryHandler to catch the queries upon buttons pressed.
def button_callback(bot, update):
# data is the callback_data where you declared in the buttons
query = update.callback_query.data
if query == "something":
# do something here
updater.dispatcher.add_handler(CallbackQueryHandler(button_callback))
This is a minimal example of how to catch the buttons' data. You can check here for a complete example.