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
}
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'm attempting to send consumers.py information to display on the client end outside of consumers.py.
I've referenced Send message using Django Channels from outside Consumer class this previous question, but the sub process .group_send or .group_add don't seem to exist, so I feel it's possible I'm missing something very easy.
Consumers.py
from channels.generic.websocket import WebsocketConsumer
from asgiref.sync import async_to_sync
class WSConsumer(WebsocketConsumer):
def connect(self):
async_to_sync(self.channel_layer.group_add)("appDel", self.channel_name)
self.accept()
self.render()
appAlarm.py
def appFunc(csvUpload):
#csvUpload=pd.read_csv(request.FILES['filename'])
csvFile = pd.DataFrame(csvUpload)
colUsernames = csvFile.usernames
print(colUsernames)
channel_layer = get_channel_layer()
for user in colUsernames:
req = r.get('https://reqres.in/api/users/2')
print(req)
t = req.json()
data = t['data']['email']
print(user + " " + data)
message = user + " " + data
async_to_sync(channel_layer.group_send)(
'appDel',
{'type': 'render', 'message': message}
)
It's throwing this error:
async_to_sync(channel_layer.group_send)(
AttributeError: 'NoneType' object has no attribute 'group_send'
and will throw the same error for group_add when stripping it back more to figure out what's going on, but per the documentation HERE I feel like this should be working.
To anyone looking at this in the future, I was not able to use redis or even memurai in Windows OS due to cost. I ended up using server side events (SSE), specifically django-eventstream, and so far it's worked great as I didn't need the client to interact with the server, for a chat application this would not work.
Eventstream creates an endpoint at /events/ the client can connect to and receive a streaming http response.
Sending data from externalFunc.py:
send_event('test', 'message', {'text': 'Hello World'})
Event listener in HTML page:
var es = new ReconnectingEventSource('/events/');
es.addEventListener('message', function (e) {
console.log(e.data);
var source = new EventSource("/events/")
var para = document.createElement("P");
const obj = JSON.parse(event.data)
para.innerText = obj.text;
document.body.appendChild(para)
}, false);
es.addEventListener('stream-reset', function (e) {
}, false);
So i have been stuck on this for a week or so and could really do this some advice.
I have a basic website which allows people to sign up to an automated newsletter that i want to send out. After adding their email on the site their address is automatically added to an audience.
I have a small python script running that then web scrapes a site and then if that returns a certain criteria it will send an automated email out via mailchimp to all the contacts in the mailchimp audience.
What i am having issue with is actually creating and sending out the email via mail chimp.
I have been through https://mailchimp.com/developer/api/marketing/campaigns/add-campaign/ a few times and can't seem to get it working. I am able to create a new campaign succesfully as well as the audience and subject line. I am unable to workout how to actually send the email with the content i want inside it however. It just saves itself as a draft and thats it.
When i try to preview the email there is nothing in it and when i click edit next to the campaign everything is ticked except for the 'content.
I have excluded th web scraping part of my program but below is the test i am running to create and sent out via the mailchimp api
import mailchimp_marketing as MailchimpMarketing
from mailchimp_marketing.api_client import ApiClientError
from mailchimp3 import MailChimp
data = {
"recipients" :
{
"list_id": 'XXXXXXXX'
},
"settings":
{
"subject_line": 'Subject of email',
"from_name": 'from_name',
"reply_to": 'reply_email',
},
"type": "regular"
}
try:
client = MailchimpMarketing.Client()
#print(client)
client.set_config({
"api_key": "XXXXXXXXXXXXXXXX",
"server": "XXXXXXX"
})
#client = MailChimp(mc_api='XXXXXXXXXXXX', mc_user="XXXXXXXXX")
client.campaigns.create(data)
response = client.campaigns.get('campaign_id')
#client.campaigns.send()
print(response)
except ApiClientError as error:
print("Error: {}".format(error.text))
This succesfully creates the campaign except without the content that i want to add and simply saves the email as a draft without send. So i guess my question is how to i edit the email content and then how do i actually initiate the send.
Thanks for any help
I also didn't find a minimal example on the web. Plus the examples in the mailchimp api documentation are severely lacking for python (only curl seems correct). Here's a minimal example:
from mailchimp_marketing import Client, api_client
# find this out at https://mailchimp.com/en/help/about-api-keys/
API_KEY = '…'
# log into your Mailchimp account and look at the URL in your browser.
# You’ll see something like https://us19.admin.mailchimp.com/
# the us19 part is the server prefix.
SERVER_PREFIX = 'us19'
try:
client = Client()
client.set_config({
"api_key": API_KEY,
"server": SERVER_PREFIX
})
# find out list id: https://mailchimp.com/en/help/find-audience-id/
campaign_data = dict(
type='regular',
recipients=dict(list_id='…'),
settings=dict(
subject_line='lorem ipsum',
from_name='John Doe',
reply_to='john#doe.com',
)
)
campaign = client.campaigns.create(campaign_data)
print(campaign)
campaign_id = campaign['id']
content_data = dict(
plain_text='lorem ipsum',
html='<p><strong>lorem</strong><br />ipsum</p>'
)
response = client.campaigns.set_content(campaign_id, content_data)
print(response)
response = client.campaigns.send(campaign_id)
print(response)
except api_client.ApiClientError as e:
print("Error: {}".format(error.text))
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.
Trying to send message with callback keybord attached to it, bot no good. Tels me
TypeError: must be str, not ReplyKeyboardMarkup
Can't find any exemples how to do it correctly.
keyboard = [[InlineKeyboardButton("Выполнено", callback_data='Done')],
[InlineKeyboardButton("MAC", callback_data='MAC'),
InlineKeyboardButton("Phone", callback_data='Phone'),
InlineKeyboardButton("История", callback_data='History')]]
reply_markup = ReplyKeyboardMarkup(keyboard)
requests.post(url='https://api.telegram.org/bot{blah}/'
'sendMessage?chat_id=' + str(query.message.chat_id) + '&text="TEST"&reply_markup=' + reply_markup)
Firstly, you should use InlineKeyboardMarkup instead of ReplyKeyboardMarkup to craete the markup object made of InlineKeyboardButtons.
Then, you probably should simply use the bot object to send the message with bot.send_message(query.message.chat_id, 'TEST', reply_markup=reply_markup).
Lastly, if you really really need to use requests to do manual HTTP request, you should provide the parameters in the requests.post()'s data.
import json
import requests
from telegram import InlineKeyboardButton, InlineKeyboardMarkup
keyboard = [[InlineKeyboardButton("Выполнено", callback_data='Done')],
[InlineKeyboardButton("MAC", callback_data='MAC'),
InlineKeyboardButton("Phone", callback_data='Phone'),
InlineKeyboardButton("История", callback_data='History')]]
reply_markup = InlineKeyboardMarkup(keyboard)
data = {"chat_id": query.message.chat_id,
"text": "TEST",
"reply_markup": json.dumps(reply_markup.to_dict())}
requests.post(url='https://api.telegram.org/bot{blah}/sendMessage', data=data)