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
Related
I am trying simple thing, add local picture to my slack channel using python script. I have not found the answer. I have created slack app for my channel and have Verification Token and APP ID.
I have tried following with no result:
import requests
files = {
'file': ('dog.jpg', open('dog.jpg', 'rb')),
'channels': (None, 'App ID,#channel'),
'token': (None, 'Verification Token'),
}
And:
import os
from slack import WebClient
from slack.errors import SlackApiError
client = WebClient(token=os.environ['SLACK_API_TOKEN'])
try:
filepath="./tmp.txt"
response = client.files_upload(
channels='#random',
file=filepath)
assert response["file"] # the uploaded file
except SlackApiError as e:
# You will get a SlackApiError if "ok" is False
assert e.response["ok"] is False
assert e.response["error"] # str like 'invalid_auth', 'channel_not_found'
print(f"Got an error: {e.response['error']}")
response = requests.post('https://slack.com/api/files.upload', files=files)
Here, when I insert my Slack apps token to SLACK_API_TOKEN , it gives me error on token.
Anyone knows quick and easy way to post local images to slack?
Thanks!
The verification token can not be used for API calls. You need a user or bot token. See this answer on how to get a token: Slack App, token for Web API
You do not need to use both requests and slack to make the API call. The latter is sufficient.
Here is an example snippet for uploading a file to Slack with the official Slack library:
import os
import slack
from slack.errors import SlackApiError
# init slack client with access token
slack_token = os.environ['SLACK_TOKEN']
client = slack.WebClient(token=slack_token)
# upload file
try:
response = client.files_upload(
file='Stratios_down.jpg',
initial_comment='This space ship needs some repairs I think...',
channels='general'
)
except SlackApiError as e:
# You will get a SlackApiError if "ok" is False
assert e.response["ok"] is False
assert e.response["error"] # str like 'invalid_auth', 'channel_not_found'
print(f"Got an error: {e.response['error']}")
I use Python telegram bot API for my bot.
I want to generate photos locally and send them as inline results but InlineQueryResultPhoto accepts only photo URLs.
Suppose my project structure looks like this:
main.py
photo.jpg
How do I send photo.jpg as an inline result?
Here is the code of main.py:
from uuid import uuid4
from telegram.ext import InlineQueryHandler, Updater
from telegram import InlineQueryResultPhoto
def handle_inline_request(update, context):
update.inline_query.answer([
InlineQueryResultPhoto(
id=uuid4(),
photo_url='', # WHAT DO I PUT HERE?
thumb_url='', # AND HERE?
)
])
updater = Updater('TELEGRAM_TOKEN', use_context=True)
updater.dispatcher.add_handler(InlineQueryHandler(handle_inline_request))
updater.start_polling()
updater.idle()
There is no direct answer because Telegram Bot API doesn't provide it.
But there are two workaounds: you can use upload a photo to telegram servers and then use InlineQueryResultCachedPhoto or you can upload to any image server and then use InlineQueryResultPhoto.
InlineQueryResultCachedPhoto
This first option requires you to previously upload the photo to telegram servers before creating the result list. Which options do you have? The bot can message you the photo, get that information and use what you need. Another option is creating a private channel where your bot can post the photos it will reuse. The only detail of this method is getting to know the channel_id (How to obtain the chat_id of a private Telegram channel?).
Now lets see some code:
from config import tgtoken, privchannID
from uuid import uuid4
from telegram import Bot, InlineQueryResultCachedPhoto
bot = Bot(tgtoken)
def inlinecachedphoto(update, context):
query = update.inline_query.query
if query == "/CachedPhoto":
infophoto = bot.sendPhoto(chat_id=privchannID,photo=open('logo.png','rb'),caption="some caption")
thumbphoto = infophoto["photo"][0]["file_id"]
originalphoto = infophoto["photo"][-1]["file_id"]
results = [
InlineQueryResultCachedPhoto(
id=uuid4(),
title="CachedPhoto",
photo_file_id=originalphoto)
]
update.inline_query.answer(results)
when you send a photo to a chat/group/channel, you can obtain the file_id, the file_id of the thumbnail, the caption and other details I'm going to skip. What the problem? If you don't filter the right query, you may end up sending the photo multiple times to your private channel. It also means the autocomplete won't work.
InlineQueryResultPhoto
The other alternative is upload the photo to internet and then use the url. Excluding options like your own hosting, you can use some free image hostings that provides APIs (for example: imgur, imgbb). For this code, generating your own key in imgbb is simpler than imgur. Once generated:
import requests
import json
import base64
from uuid import uuid4
from config import tgtoken, key_imgbb
from telegram import InlineQueryResultPhoto
def uploadphoto():
with open("figure.jpg", "rb") as file:
url = "https://api.imgbb.com/1/upload"
payload = {
"key": key_imgbb,
"image": base64.b64encode(file.read()),
}
response = requests.post(url, payload)
if response.status_code == 200:
return {"photo_url":response.json()["data"]["url"], "thumb_url":response.json()["data"]["thumb"]["url"]}
return None
def inlinephoto(update, context):
query = update.inline_query.query
if query == "/URLPhoto":
upphoto = uploadphoto()
if upphoto:
results = [
InlineQueryResultPhoto(
id=uuid4(),
title="URLPhoto",
photo_url=upphoto["photo_url"],
thumb_url=upphoto["thumb_url"])
]
update.inline_query.answer(results)
This code is similar to the previous method (and that includes the same problems): uploading multiple times if you don't filter the query and you won't have the autocomplete when writing the inline.
Disclaimer
Both code were written thinking the images you want to upload are generated at the moment you receive the query, otherwise you can do the work previous to receiving the query, saving that info in a database.
Bonus
You can run your own bot to get the channel_id of your private channel with pyTelegramBotAPI
import telebot
bot = telebot.TeleBot(bottoken)
#bot.channel_post_handler(commands=["getchannelid"])
def chatid(message):
bot.reply_to(message,'channel_id = {!s}'.format(message.chat.id))
bot.polling()
To get the id you need to write in the channel /getchannelid#botname
i using dialogflow v2 with python sdk.
All works fine, except when i add a new intent with its training phrases. The bot doesnt recognize the phrases until i enter through the web console and save the intent, when the training start, after that, the bot works well.
I tried to train the intent using the python sdk:
agent_client = dialogflow.AgentsClient(credentials=self.credentials)
response = agent_client.train_agent('projects/' + self.project_id)
The response is 200, but the agent wasnt trained.
Thanks to any clue how to make this work.
May be, it helps:
def train_agent(project_id):
from google.cloud import dialogflow
agents_client = dialogflow.AgentsClient()
parent = dialogflow.AgentsClient.common_project_path(project_id)
response = agents_client.train_agent(
request={"parent": parent}
)
print(response.done())
P.S.: GOOGLE_APPLICATION_CREDENTIALS in my .env
This works for me. Currently, I'm using FastApi. The secret is to add the function done(). That would return true or false if the operation finished successfully.
#router.post("/chatbot/train/{project_id}", response_model=IGetResponseBase)
async def train_agent(
project_id: str,
) -> Any:
# Create a client
agent_client = AgentsAsyncClient()
parent = agent_client.common_project_path(project_id)
# Initialize request argument(s)
request = TrainAgentRequest(
parent=parent,
)
# Make the request
operation = await agent_client.train_agent(request=request)
print("Waiting for operation to complete...")
response = await operation.done()
# Handle the response
print('operation', response)
i've just started working with line-bot and followed the tutorial here: https://developers.line.biz/en/docs/messaging-api/building-bot/
However, I still don't understand how I can connect with my line app account, to send messages, and have these messages appear back in python.
The below is the script I copied from line tutorial.
from flask import Flask, request, abort
from linebot import LineBotApi, WebhookHandler
from linebot.exceptions import InvalidSignatureError
from linebot.models import MessageEvent, TextMessage, TextSendMessage
app = Flask(__name__)
line_bot_api = LineBotApi('foo', timeout=20)
handler = WebhookHandler('bar')
user_profile = 'far'
#app.route("/", methods=['GET'])
def home():
profile = line_bot_api.get_profile(user_profile)
print(profile.display_name)
print(profile.user_id)
print(profile.picture_url)
print(profile.status_message)
return '<div><h1>ok</h1></div>'
#app.route("/callback", methods=['POST'])
def callback():
# get X-Line-Signature header value
signature = request.headers['X-Line-Signature']
# get request body as text
body = request.get_data(as_text=True)
app.logger.info("Request body: " + body)
# handle webhook body
try:
handler.handle(body, signature)
except InvalidSignatureError:
abort(400)
return 'OK'
#handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
line_bot_api.reply_message(
event.reply_token,
TextSendMessage(text='hello world'))
if __name__ == "__main__":
app.run(debug=True)
What am I missing, or how can I connect with the line app to send and receive messages?
I followed that tutorial and was able to successfully create a bot that just echoes messages in uppercase:
Your question is how to "connect" your bot's code with the LINE app. The three most important parts of the tutorial are probably:
Adding the bot as a friend, you do this by scanning its QR code with the LINE app
When you create a channel for your bot, you need to enable "Webhooks" and provide an https endpoint which is where LINE will send the interaction events your bot receives. To keep this simple for the purposes of this answer, I created an AWS Lambda function and exposed it via API Gateway as an endpoint that looked something like:
https://asdfasdf.execute-api.us-east-1.amazonaws.com/default/MyLineBotFunction. This is what I entered as the Webhook URL for my bot.
Once you are successfully receiving message events, responding simply requires posting to the LINE API with the unique replyToken that came with the message.
Here is the Lambda function code for my simple yell-back-in-caps bot:
import json
from botocore.vendored import requests
def lambda_handler(event, context):
if 'body' in event:
message_event = json.loads(event['body'])['events'][0]
reply_token = message_event['replyToken']
message_text = message_event['message']['text']
requests.post('https://api.line.me/v2/bot/message/reply',
data=json.dumps({
'replyToken': reply_token,
'messages': [{'type': 'text', 'text': message_text.upper()}]
}),
headers={
# TODO: Put your channel access token in the Authorization header
'Authorization': 'Bearer YOUR_CHANNEL_ACCESS_TOKEN_HERE',
'Content-Type': 'application/json'
}
)
return {
'statusCode': 200
}
I am trying to use my bot to delete certain messages in a slack channel with this api call
import os
import time
import re
from slackclient import SlackClient
slack_client = SlackClient(
'xsssssseeeeeeee')
slack_mute_bot_id = None
def delete_message(slack_event):
for event in slack_event:
if event["type"] == "message":
message_text = event['text']
time_stamp = event['ts']
channel_id = event['channel']
slack_client.api_call(
'chat.delete',
channel=channel_id,
ts=time_stamp,
as_user=True
)
print(message_text + " delted")
if __name__ == "__main__":
if slack_client.rtm_connect(with_team_state=False):
slack_mute_bot_id = slack_client.api_call("auth.test")["user_id"]
while True:
# print(slack_client.rtm_read())
delete_message(slack_client.rtm_read())
time.sleep(1)
else:
print("Connection failed. Exception traceback printed above.")
I do not get any error message after doing this and the bot does not delete the message. I am using the bot user token. I have benn able to send message succesfully but the delete method does not work and still gives np responses
Refer - https://api.slack.com/methods/chat.delete
When used with a user token, this method may only delete messages
that user themselves can delete in Slack.
When used with a bot token, this method may delete only messages
posted by that bot.
I got stumbled into the same thing.