how to take input from user on slack to proceed further? - python

Im working on chatbot where bot ask users name and then bot replies with Greeting + name. This works when I use this on terminal with input() but not able to figure out how to accept input from slack and use that input.
def start(request, channel):
response = ('\n\nHello!')
send_response(response, channel)
name = ('Please tell me your name.\n')
send_response(name, channel)
name = request
greet = "Hello" + name
send_response(greet, channel)
def send_response(response,channel):
slack_client.api_call("chat.postMessage", channel=channel, text=response, as_user=True)
def parse_slack_output(slack_rtm_output):
output_list = slack_rtm_output
if output_list and len(output_list) > 0:
for output in output_list:
if output and 'text' in output and AT_BOT in output['text']:
# return text after the # mention, whitespace removed
return output['text'].split(AT_BOT)[1].strip(), \
output['channel']
return None, None
if __name__ == "__main__":
READ_WEBSOCKET_DELAY = 1 # 1 second delay between reading from firehose
if slack_client.rtm_connect():
print ("connected and running!")
while True:
request, channel = parse_slack_output(slack_client.rtm_read())
if request and channel:
start(request, channel)
time.sleep(READ_WEBSOCKET_DELAY)
else:
print("Connection failed. Invalid Slack token or bot ID?")

As per slack doc, dialog.open() method is the way to achieve your requirement.
https://api.slack.com/dialogs.
EDIT:
And RASA NLU-CORE gives more option for conversational based ChatBots. http://rasa.com/docs/core/quickstart/
Slot Filling is what you need to look into to store the name or any other values and use it further in the conversation.

Related

Discord.py returning user's name when I asked for user's display_name

When I try to get the user's display name it returns their Discord name.
No matter what method I try display_name is never part of the return list.
Just to make sense of it, if the user mentions someone with "no ping" in their display name, it will go through all the channels in the server looking for mentions in the last 10 minutes.
for i in range(len(message.mentions)): # Unimportant, just for clarity
if "no ping" in message.mentions[i].display_name.lower() or \ # Unimportant, just for clarity
"unavailable" in message.mentions[i].display_name.lower() or \ # Unimportant, just for clarity
"unavailable" in message.mentions[i].display_name.lower(): # Unimportant, just for clarity
counter = 0
text_channel_list = []
for TextChannel in message.guild.channels:
if str(TextChannel.type) == 'text':
text_channel_list.append(TextChannel.id)
prev = datetime.datetime.now() - datetime.timedelta(minutes=10)
for i in range(len(text_channel_list)):
channel = client.get_channel(text_channel_list[i])
msg = await channel.history(limit=None, after=prev).flatten()
for message2 in msg:
if message2.author == message.author:
for i in range(len(message2.mentions)):
print(message2.mentions[i].display_name) # This will return the user's Discord name, I want it to return the Server display name.
if "no ping" in message2.mentions[i].display_name.lower():
counter += 1
I just encountered this issue and fixed it by expanding the scope of intents to all:
client = discord.Client(intents=discord.Intents.all())
Hope this helps someone.

Not able to break from loop while running a Telegram Bot

I am creating a Telegram Bot using pyTelegramBotAPI that sends real-time updates of ongoing cricket matches. I want to break the loop whenever the user enters the "/stop" command. I've looked up various sources and also tried several methods to achieve the same but all in vain. The loop continues to iterate. The closest I've reached is by exiting the program by raising an error. Also, while inside the loop, the getUpdates method always returns an empty list. I've also written an issue for the same on GitHub.
def loop(match_url):
prev_info = ""
flag = 1
#continuously fetch data
while flag:
response = requests.get(match_url)
info = response.json()['score']
#display only when the score updates
if str(info) != prev_info:
prev_info = str(info)
send_msg(info)
else:
pass
send_msg(info)
#this handler needs to be fixed
#bot.message_handler(commands=['stop', 'end'])
def stop(message):
#code to break the loop
flag = 0
return
Since this was not working, I willingly used this wrong method:
while flag:
response = requests.get(match_url)
info = response.json()['score']
if str(info) != prev_info:
prev_info = str(info)
send_msg(info)
else:
pass
send_msg(info)
#bot.message_handler(commands=['stop', 'end'])
def stop(message):
bot.polling.abort = True #an arbitrary function that raises error and exits the program
Here's the whole code. I've also added my GitHub link of this code:
import requests, json, telebot
token = <TOKEN>
bot = telebot.TeleBot(token)
#parsing data from cricapi.com
def live_matches():
#here I'm using the KEY obtained from cricapi.com
curr_matches_url = "https://cricapi.com/api/cricket?apikey=<KEY>"
curr_matches = requests.get(curr_matches_url)
match_data = curr_matches.json()['data']
global unique_id_arr, score_arr
unique_id_arr, score_arr = [], []
match_details = ""
for i in match_data:
unique_id_arr.append(i["unique_id"])
for i in range(len(match_data)):
score_arr.append(match_data[i]["title"])
score_arr[i] += "\n"
match_details += str(i+1) + ". "
match_details += score_arr[i]
send_msg(match_details)
def send_msg(msg):
url2 = 'https://api.telegram.org/bot'+token+'/sendMessage'
data = {'chat_id': chat_id, 'text': msg}
requests.post(url2, data).json()
#bot.message_handler(commands=['start', 'help'])
def send_welcome(message):
bot.reply_to(message, "Howdy, how are you doing?")
global chat_id
chat_id = message.chat.id
msg = bot.reply_to(message, "Welcome to test project\nEnter the match number whose updates you want to receive")
live_matches()
bot.register_next_step_handler(msg, fetch_score)
def fetch_score(message):
chat_id = message.chat.id
match_no = message.text
#checking if the number entered is present in the displayed list
if not match_no.isdigit():
msg = bot.reply_to(message, 'Error1!\nSelect a no. from the above list only')
return bot.register_next_step_handler(msg, fetch_score)
elif 1 <= int(match_no) <= len(score_arr):
unique_id = unique_id_arr[int(match_no)-1]
global match_url
#get the data of the desired match
match_url = "https://cricapi.com/api/cricketScore?unique_id="+unique_id+"&apikey=<KEY>"
loop(match_url)
else:
msg = bot.reply_to(message, "Error2!\nSelect a no. from the above list only")
return bot.register_next_step_handler(msg, fetch_score)
def loop(match_url):
prev_info = ""
flag = 1
#continuously fetch data
while flag:
response = requests.get(match_url)
info = response.json()['score']
#display only when the score updates
if str(info) != prev_info:
prev_info = str(info)
send_msg(info)
else:
pass
send_msg(info)
#this handler needs to be fixed
#bot.message_handler(commands=['stop', 'end'])
def stop(message):
#an arbitrary function that raises error and then exits
bot.polling.abort = True
bot.polling()
"""
#currently not using
def receive_msg():
url1 = 'https://api.telegram.org/bot'+token+'/getUpdates'
response = requests.get(url1)
text = response.json()['result']
if len(text) > 0:
user_msg = text[-1]['message']['text']
return user_msg
return text
"""
You are using telebot(pyTelegramBotAPI) package in the wrong way:
Why did you create your own function send_msg where there is already send_message method in telebot exists?
You are redeclaring your "stop" handler in the loop, which is wrong!
My suggestion to you is to learn how to use the pyTelegramBotAPI properly!
Here is a demonstration code, that solves your problem:
import telebot
from time import sleep
bot = telebot.TeleBot(BOT_TOKEN)
flag = 1
#bot.message_handler(commands=['loop'])
def loop(msg):
while flag:
bot.send_message(msg.chat.id, "ping")
sleep(1)
#bot.message_handler(commands=['stop', 'end'])
def stop(msg):
global flag
flag = 0
bot.send_message(msg.chat.id, "stopped")
bot.polling(none_stop=True)
Explanation:
Declared flag as a global variable and set it to 1
"loop" handler for starting the loop that sends you "ping" message every second
"stop" handler that changes flag to 0, which terminates your running loop

how to send a message and wait for a reply in python, twilio in whatsapp

I want to take the details of a person on whatsapp and store it but it seems its not working as I want it to. It's not waiting for the user to input the first data before the second one is coming.
This is my models.py:
class student_Account(models.Model):
name = models.CharField(max_length = 30)
place_of_stay = models.CharField(max_length = 30)
def __str__(self):
return self.name
and this is my views.py:
#csrf_exempt
def sms(request):
incoming_msg = request.POST.get('Body', '').lower()
resp = MessagingResponse()
msg = resp.message()
msg1 = resp.message()
if 'hi' in incoming_msg:
reply = ("Hello and welcome to kkk banking system WhatsApp bot!\n\n"
"What would you like to do\n"
"1. Create an accout?\n"
"2. Check your account balance\n")
msg.body(reply)
if incoming_msg == '1':
reply = ("Enter your name")
a = incoming_msg
student.name = a
reply = ("Enter your place of stay")
b = incoming_msg
student.place_of_stay = b
msg.body(reply)
student.save()
reply = ("Your details has been saved!!.")
msg.body(reply)
Every answer/response by your user via WhatsApp/SMS will be a new call to your sms method, i.e. you need to either A) split your logic to collect the data you need or B) let them enter it in one go.
Re A): You could save the data in the session, a cache or your model to keep track whether the user has answered a question (e.g. identified by the user's phone number because this is submitted each time). You will need to find a way to identify the answers. Maybe with "Enter your place of stay" the user can only pick from a selected number of answers? Then you could do an if checking if the incoming_msg is one of those and otherwise it'll probably be an answer to the other question, e.g. pseudocode:
if incoming_msg == 'hi':
# Show welcome message
# return message
elif incoming_msg == '1':
# Show first question
# return message
elif incoming_msg in [<list of available places>]:
# Retrieve current user from session/cache
# Save place of stay
# return message
else:
# Save name
# Update session/cache
# Form second question
# Return message
Re B): You could let the user submit something like <name> <place of stay> in one go, e.g. Joseph My place of stay and then you split the answer in your business logic.

Getting input from users in Bot

I have a question about building a telegram bot with python.
How can I get input from the user in my python-telegram-bot?
For example, a dictionary bot, how can I get a word from the user?
I recommend to have a look at the examples on GitHub.
With python-telegram-bot v12.0.0b1 you can do it like this:
def do_something(user_input):
answer = "You have wrote me " + user_input
return answer
def reply(update, context):
user_input = update.message.text
update.message.reply_text(do_something(user_input))
def main():
updater = Updater("TOKEN", use_context=True)
dp = updater.dispatcher
dp.add_handler(MessageHandler(Filters.text, reply))
updater.start_polling()
updater.idle()
I recommend pyTelegramBotAPI, not python-telegram-bot.
For me it is easier.
And you should use this:
#bot.message_handler(func=lambda message: True)
def echo_message(message):
cid = message.chat.id
mid = message.message_id
message_text = message.text
user_id = message.from_user.id
user_name = message.from_user.first_name
You can save this information in JSON if you want.

Skype4py !command with arguments

I currently have a skypebot which replies to commands and pings websites when I use the following code:
if Status == 'SENT' or (Status == 'RECEIVED'):
if Message.Body.lower() == '!ping google':
ping = os.system("ping google.com")
if ping == 0:
Message.Chat.SendMessage("Online!")
else:
Message.Chat.SendMessage('Offline!')
This works and if the website is online it will display Online! in chat. However, it requires me to define the website before hand. I have searched for a good few hours now to try to find how I would make it so I can do !ping [website] and allow for the user at any time to use whatever website they want. Any ideas?
I would do something like this:
body = Message.Body
if body.startswith('!'):
parts = body.split() # ['!ping', 'google.com']
command = parts[0][1:] # 'ping'
result = commands[command](*parts[1:]) # Calls `ping` with 'google.com'
Message.Chat.SendMessage(result) # Prints out the resulting string
Now, you can define simple functions:
def ping(url):
if os.system("ping " + url) == 0:
return 'Online!'
else:
return 'Offline!'
And add them to a commands dictionary:
commands = {
'ping': ping
}
os.system() is insecure if you're expecting arbitrary user input, so I'd use subprocess.Popen instead (or just try connecting to the website with just Python).
I have a SkypeBot I made as well.
I use http://www.downforeveryoneorjustme.com/
I do it this way:
Functions.py
def isUP(url):
try:
source = urllib2.urlopen('http://www.downforeveryoneorjustme.com/' + url).read()
if source.find('It\'s just you.') != -1:
return 'Website Responsive'
elif source.find('It\'s not just you!') != -1:
return 'Tango Down.'
elif source.find('Huh?') != -1:
return 'Invalid Website. Try again'
else:
return 'UNKNOWN'
except:
return 'UNKNOWN ERROR'
And for commands.py
elif msg.startswith('!isup '):
debug.action('!isup command executed.')
send(self.nick + 'Checking website. Please wait...')
url = msg.replace('!isup ', '', 1)
url = functions.getCleanURL(url)
send(self.nick + functions.isUP(url))
Of course with "import functions" in the commands.py file.
I'm sure you can alter this a bit to work to check a website's status for your bot as well.
Good luck :)

Categories

Resources