I'm v new to creating chatbots.
import telebot
bot = telebot.TeleBot('123345677789')
def sendMessage(message, text):
bot.send_message(message.chat.id, text)
#bot.message_handler(func=lambda msg: msg.text is not None)
def reply_to_message(message):
if 'hello' in message.text.lower():
sendMessage(message, 'Hello! How are you doing today?')
else:
bot.reply_to(message,'try hi or hello')
#bot.message_handler(func=lambda msg: msg.text is not None)
def getresponse(user_input):
if 'virus' in user_input.text.lower():
url = "https://covid-19-coronavirus-statistics.p.rapidapi.com/v1/stats"
querystring = {"country":"USA"}
headers = {
'x-rapidapi-host': "covid-19-coronavirus-statistics.p.rapidapi.com",
'x-rapidapi-key': "ea33a4fd9cmshd4ead0c7290"}
response = requests.request("GET", url, headers=headers, params=querystring)
bot.reply_to(user_input,response.text)
else:
bot.reply_to(user_input,'type virus')
I've been trying to get the api to return the data. But whenever i try to send the requests, the bot doesnt remind me anything. Any help is appreciated.
Thanks!
The problem is that you have the same filter for both functions, so the first function will always take the priority and answer your messages. Your options would be: fuse both functions, delete the first function, changing from message to command one of your functions or you can try using register_next_step_handler() so you always have to salute the bot before asking for information (sounds like overkill to me).
Ok, lets go with fusing:
import telebot
import requests
bot = telebot.TeleBot(tgtoken)
def sendMessage(message, text):
bot.send_message(message.chat.id, text)
#bot.message_handler(func=lambda msg: msg.text is not None)
def getresponse(user_input):
if user_input.text.lower() in ["hello", "hi"]:
sendMessage(user_input, 'Hello! How are you doing today?')
elif 'virus' in user_input.text.lower():
url = "https://covid-19-coronavirus-statistics.p.rapidapi.com/v1/stats"
querystring = {"country":"Denmark"}
headers = {
'x-rapidapi-host': "covid-19-coronavirus-statistics.p.rapidapi.com",
'x-rapidapi-key': rapidapitoken}
response = requests.request("GET", url, headers=headers, params=querystring)
if not response.json()["error"]:
bot.reply_to(user_input,str(response.json()["data"]))
else:
bot.reply_to(user_input,"Error: {!s} , StatusCode: {!s}, Message: {!s}".format(response.json()["error"], response.json()["statusCode"], response.json()["message"]))
else:
bot.reply_to(user_input,'type hi, hello, or virus')
bot.polling()
And that's it. Ok, I cheated, I used Denmark and not USA because Denmark information is small compared to USA. But that wasn't the question, riiiiight? Well, the best way to solve it is to send the minimum information required because otherwise you will hit two limits: max characters in a message and too many requests if you split the message.
PS: Maybe the code when you show the error you get at retrieving the information from the API isn't perfect, I couldn't test it.
Related
I'm a noobie at Python and was just messing around, but now I'm really curious why it isn't working. I'm currently trying to build a telegram bot that generates an image based on the text given to the bot. I think there might be a problem with my DeepAI api? When I click this link: https://api.deepai.org/api/text2img i always get the error
{"err": "error processing given inputs from request"}
. The bot is linked but gives me the error as in the code below. My code below:
import requests
import json
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters
def text_to_image(update, context):
# Get the text from the user
text = update.message.text
# Set up the DeepAI API request
api_key = "{{ api }}"
headers = {
"api-key": api_key
}
data = {
"text": text
}
# Make the request to the DeepAI API
response = requests.post("https://api.deepai.org/api/text2img", headers=headers, json=data)
if response.status_code != 200:
update.message.reply_text("An error occurred while generating the image. Please try again later.")
return
# Get the generated image from the response
response_json = response.json()
image_url = response_json["output_url"]
# Send the generated image to the user
context.bot.send_photo(chat_id=update.effective_chat.id, photo=image_url)
def main():
# Set up the Telegram bot
updater = Updater(token="{{ api }}", use_context=True)
dispatcher = updater.dispatcher
# Add the text_to_image handler
text_to_image_handler = MessageHandler(Filters.text, text_to_image)
dispatcher.add_handler(text_to_image_handler)
# Start the bot
updater.start_polling()
updater.idle()
if __name__ == '__main__':
main()
I've tried changing code and different things but nothing seems to work, i'm really stuck right now
From the looks of it, it's an error on the API side of things. The status code of the API server depends on traffic and account/key.
Things to do:
Check if your API key is valid and wait when server works on google, then try to run your code
I am building a custom responder for the Cortex/Hive, and I have been unable to get my request response to properly convert into a JSON format. When testing in the local development environment, my code in getCount function works flawlessly, but when adding the cortex responder wrapper to it, my code fails.
Since the responder runs from Cortex, I do not receive an error message beyond "input: null", so I had to write to an error log. Using this log, I determined that the error stems from the line data = json.loads(response.text). I tried using simple json, regex-ing the desired value from response.text, changing encoding methods, and banging my head on the keyboard from the sheer stupidity of it not working.
CODE:
import requests
import json
from cortexutils.responder import Responder
class Search(Responder):
def __init__(self):
# Debug
with open('/xxx/xxx/xxx/xxx/error.log','a') as error_log:
error_log.write('Starting: \n')
error_log.write('\n\n')
# End Debug
Responder.__init__(self)
self.apiuser = self.get_param('config.api_user', None)
self.apikey = self.get_param('config.api_key', None)
self.url = self.get_param('config.api_url', None)
self.ioc_type = self.get_param('data.dataType', None)
self.ioc = self.get_param('data.data', None)
# Debug
with open('/xxx/xxx/xxx/xxx/error.log','a') as error_log:
error_log.write('User ID: \n')
error_log.write(self.apiuser)
error_log.write('\n\nSecret: \n')
error_log.write(self.apikey)
error_log.write('\n\n')
error_log.write('IOC Type: \n')
error_log.write(self.ioc_type)
error_log.write('\n\n')
error_log.write('Value: \n')
error_log.write(self.ioc)
error_log.write('\n\n')
# End Debug
def getCount(self):
with open('/xxx/xxx/xxx/xxx/error.log','a') as error_log:
error_log.write('Starting Count: \n')
error_log.write('\n\n')
url = self.url
headers={'Content-Type': 'application/json'}
params={'type': self.ioc_type, 'value': self.ioc}
response = requests.request("GET", url, headers=headers, params = params, auth=(self.apiuser, self.apikey))
data = json.loads(response.text)
with open('/xxx/xxx/xxx/xxx/error.log','a') as error_log:
error_log.write('Response: ')
error_log.write(data)
deviceCount = data['resources'][0]['device_count']
self.count = deviceCount
def run(self):
Responder.run(self)
self.getCount()
self.operations()
def operations(self):
return [self.build_operation('AddTagToCase', tag= self.count)]
if __name__ == '__main__':
Search().run()
Results from response.text:
{"meta":{"query_time":0.014920091,"trace_id":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"},
"resources":[{"id":"sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"type":"sha256",
"value":"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"device_count":11}],"errors":[]}
Error Logging results:
Starting:
User ID:
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Secret:
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
IOC Type:
sha256
Value:
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
run starting:
Starting Count:
self.count should be equal to device_count, but json.loads fails to format this response. This can be seen in my error log results where Count() starts but abruptly ends before data is written to it.
If you could please provide insight into why this fails to format the response properly, please shed some light.
Thank you
This is my standard way of getting a json response from an API using the requests module
response = requests.get(url, headers=headers, params=params, auth=(self.apiuser, self.apikey)).json()
I am new to messenger platform, I did search a lot on the internet how to make a "get started" button on messenger in python but there is no answer.
Below is my code:
def send_get_started(bot,recipient_id):
button = {
"get_started":{
"payload" : "first_coming"
}
}
bot.send_raw(button)
the send_raw function here I get from bot.py in pymessenger2 on python
which is here (also the code below)
def send_raw(self, payload):
request_endpoint = '{0}/me/messages'.format(self.graph_url)
response = requests.post(
request_endpoint,
params=self.auth_args,
data=json.dumps(payload, cls=AttrsEncoder),
headers={'Content-Type': 'application/json'})
result = response.json()
return result
Of course it did not work, I think I misunderstand somewhere, could somebody show me my problem?
Thanh you so much.
The endpoint should be:
https://graph.facebook.com/v2.6/me/messenger_profile
You could see this in the reference: Get Started Reference
The endpoint is wrong. Your request is using the '/messages' path when it should be using '/thread_settings'
When setting the 'Get Started' button or the Greeting you need to use the endpoint
https://graph.facebook.com/v3.0/me/thread_settings
I've tried to create my first telegram bot hosting the code as an amazon lambda instance, i suppose i should return something to the webhook 'cause it keep saying "Wrong response from the webhook: 502 Bad Gateway".
Here is part of my code:
def msgSend(text, chat_id):
url = URL + "sendMessage?text={}&chat_id={}".format(text, chat_id)
response = requests.get(url)
content = response.content.decode("utf8")
return content
def handle(msg):
sender = msg['from']['username']
id_gruppo = msg['chat']['id']
if sender == NAME:
testo = msg['text']
usernames = [x.replace('#','') for x in rx.findall(text)]
map(foo, usernames)
msgSend(confirm_mess, id_group)
return
def main(event, context):
response = ast.literal_eval(event['body'])
handle(response['message'])
return {
'something': 'something'
}
Actually the process works fine enough, the messages are received by my lambda and everything works like a charm, except for one thing, the confirmation message is sent over and over endlessly and the webhooks never marks the messages as read.
here is the response of getWebHookInfo:
{"ok":true,"result":{"url":"https://t2rt9guj3h.execute-api.us-west-2.amazonaws.com/prod/instabot","has_custom_certificate":false,"pending_update_count":19,"last_error_date":1489331750,"last_error_message":"Wrong response from the webhook: 502 Bad Gateway","max_connections":40}}
According to the bot helper the wh requires a 2XX code response...
Any idea about that?
According to the bot helper the wh requires a 2XX code response...
This is true. Your last statement should be
return {
statusCode: 200
}
If you don't return a successful response code, Telegram won't know what to do with it, which is why you see the HTTP 502 Bad Gateway. I was hitting this for awhile also :)
I wrote a telegram bot. All things went well and it worked well. But when I want to use ReplyKeyboardMarkup as it mentioned in its document, it did not work! I mean the keyboard doesn't show up.
This JSON object has a key keyboard and its value ,according to its doc, is:
type: Array of Array of String.
description: Array of button rows, each represented by an Array of Strings
This is my code for sending the request:
reply_markup = {'keyboard': [['1'],['2']], 'resize_keyboard': True, 'one_time_keyboard': True}
params = urllib.urlencode({
'chat_id': str(chat_id),
'text': msg.encode('utf-8'),
'reply_markup': reply_markup,
'disable_web_page_preview': 'true',
# 'reply_to_message_id': str(message_id),
})
resp = urllib2.urlopen(BASE_URL + 'sendMessage', params).read()
You have to serialize reply_markup to JSON string separately, like in this answer Telegram bot custom keyboard in PHP
Because it still took me a bit of trial and error to get in right in Python even after reading the PHP answer linked to by Kostya, here is a the adapted Python code that works (you just need to add your bot's token and a chat ID to send the message to).
Note that I also had to update my Telegram client to the newest version (currently 3.1) to see the result.
import urllib
import urllib2
import json
TOKEN = "<your bot token>"
chat_id = <your chat id>
msg = "some string"
BASE_URL = "https://api.telegram.org/bot{}/".format(TOKEN)
reply_markup = {'keyboard': [['1'],['2']], 'resize_keyboard': True, 'one_time_keyboard': True}
reply_markup = json.dumps(reply_markup)
params = urllib.urlencode({
'chat_id': str(chat_id),
'text': msg.encode('utf-8'),
'reply_markup': reply_markup,
'disable_web_page_preview': 'true',
# 'reply_to_message_id': str(message_id),
})
resp = urllib2.urlopen(BASE_URL + 'sendMessage', params).read()
If you like you can try this method
import telegram
from telegram.ext import Updater
updater = Updater(token='BOT_TOKEN')
dispatcher = updater.dispatcher
updater.start_polling()
def test(bot, update):
results = bot.sendMessage(chat_id=update.message.chat_id, text="Test", reply_markup={"keyboard":[["Test1"], ["Test2"], ["Test3"], ["Test4"]})
print results
dispatcher.addTelegramCommandHandler('test', test)
This import makes things a lot more short, I just started using it today python-telegram-bot 3.4
The following snippet will work:
reply_markup = {
"keyboard": [[{"text":"1"}], [{"text":"2"}]],
"resize_keyboard": True,
"one_time_keyboard": True
}