How to take multiple inputs on Twilio-Whatsapp? - python

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.

Related

How to accept user input in an embedded message Discord.py

I was wondering how I would be able to accept user input from an embedded message like this image does:
Doesn't have to be exactly like that, but I want a guild member to be able to input information into an embedded message. I haven't been able to find anything about it in Discord.py API
The image shown is embedded message which does not take input but shows the output after taking input from a user as a text form. You can use the code given below:
#bot.event()
async def on_message(message):
if message.author==bot.user:
return
msg = message.content
if msg.startswith("!cal "):
names = msg.split("!cal ",1)[1]
data = names.split("*")
a = data[0]
b = data[1]
c=int(a)*int(b)
r=str(c)
em=discord.Embed(title=f"Calculator",description=f"Input\n```{a}*{b}```\n\nOutput\n```{r}```")
await message.channel.send(embed=em)
You can use this code to show the same result.
NOTE : User must enter the command properly as !cal 5*5
In the Discord API there's no way to accept an user input, but you can do something like this:
ctx.send(embed=discord.Embed(title="Hey", description="Tell me something!"))
msg = Bot.wait_for("message")
ctx.send(embed=discord.Embed(title="You said...", description=msg.content)
If you want some information from the user who used the command, try this:
while True:
msg = Bot.wait_for("message")
if (msg.author == ctx.author):
break
Then, you may like to do something like this:
# Same stuff as before...
result = eval(msg.content)
ctx.send(embed=discord.Embed(title="Result", description=result))
This will work like the calculator you shown in the answer.

How to do a "typing_on" post with pymessenger to FB messenger?

I'm trying to set my chatbot to display a typing bubble before sending the user the response so that it's more human like. I followed the documentation but am still getting instant responses from the bot with no typing bubble. As per the documentation I am using this sender action:
{"recipient":{"id":recipient_id}, "sender_action":"typing_on"}
And to put it in context, here is how I'm using it in the flask app:
#app.route('/', methods=['GET', 'POST'])
def receive_message():
global tag, latest_message
if request.method == 'GET':
# Before allowing people to message your bot Facebook has implemented a verify token
# that confirms all requests that your bot receives came from Facebook.
token_sent = request.args.get("hub.verify_token")
return verify_fb_token(token_sent)
# If the request was not GET, it must be POSTand we can just proceed with sending a message
# back to user
else:
# get whatever message a user sent the bot
output = request.get_json()
for event in output['entry']:
messaging = event['messaging']
for message in messaging:
if message.get('message'):
# Facebook Messenger ID for user so we know where to send response back to
recipient_id = message['sender']['id']
if message['message'].get('text'):
response_sent_text = send(message['message'].get('text'))
send_message(recipient_id, response_sent_text)
latest_message = response_sent_text
return "Message Processed"
def send_message(recipient_id, response):
# sends user the text message provided via input response parameter
typing_payload = {"recipient":{"id":recipient_id}, "sender_action":"typing_on"}
bot.send_raw(typing_payload)
print(bot.send_raw(typing_payload))
bot.send_text_message(recipient_id, response)
return "success"
Any ideas would be much appreciated!
You should pass a string representation of the payload (not a dictionary).
try doing something like this:
import json
...
def send_message(recipient_id, response):
# sends user the text message provided via input response parameter
typing_payload = json.dumps({"recipient":{"id":recipient_id}, "sender_action":"typing_on"})
bot.send_raw(typing_payload)
print(bot.send_raw(typing_payload))
bot.send_text_message(recipient_id, response)
return "success"
Also it's best practice to send these indicators upon receiving message (to show the typing indicator while processing), as opposed to directly before sending message.

Wait for user input before a send_message

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.

How to forward every channels updates using Telethon

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.

How to fetch last 10 messages from IMAP server?

I use imaplib2 library to search the last 10 messages with such command:
imap_client.search(None, '{}:{}'.format(last_uid, last_uid - 9))
But to get last_uid I need exec every time command like this:
imap_client.select("INBOX", readonly=True)
to get last UID.
Are the any ways to:
get last UID without select() command fetch last 10 messages
without last UID. Maybe there are any search criterias like 'LAST' or '-10:'?
I can not exec command like this client.search(None, 'ALL'), because IMAP server have more than 50K messages.
For any future travelers who seek an answer to this, I came up with code from the hint given by #arnt.
svr = imaplib.IMAP4_SSL(server)
if svr.login(user=user, password=password):
print('User ' + user + ' logged in successfully.')
else:
print('Login for the user ' + user + " was denied. Please check your credentials.")
x = svr.select('inbox', readonly=True)
num = x[1][0].decode('utf-8')
#from here you can start a loop of how many mails you want, if 10, then num-9 to num
resp, lst = svr.fetch(num, '(RFC822)')
body = lst[0][1]
email_message = email.message_from_bytes(body)
For me this was quite handy as I was accessing an email with more than 67000 emails in it.
You can get the last UID using the STATUS (UIDNEXT) command. However, you have to select the mailbox in order to retrieve messages, and when you issue SELECT, you'll get a message count back, which the Python imaplib's select returns.
So all you need is:
(status, response_text) = mailbox.select("inbox")
# response_text usually contains only one bytes element that denotes
# the message count in an ASCII string
message_count = int(response_text[0].decode("ascii"))
and then you can fetch the messages by index from message_count - 9 through message_count.
Note that messages are index starting at one.

Categories