how to send photo by telegram bot using multipart/form-data - python

I have a telegram bot (developed in python) and i wanna to send/upload photo by it from images that are in my computer.
so i should do it via multi part form data.
but i don't know ho to do it. also i didn't find useful source for this on Internet and on telegram documentation .
i tried to do that by below codes. but it was wrong
data = {'chat_id', chat_id}
files = {'photo': open("./saved/{}.jpg".format(user_id), 'rb')}
status = requests.post("https://api.telegram.org/bot<TOKEN>/sendPhoto", data=data, files=files)
can anyone help me?

Try this line of code
status = requests.post("https://api.telegram.org/bot<TOKEN>/sendPhoto?chat_id=" + data['chat_id'], files=files)

Both answers by Delimitry and Pyae Hlian Moe are correct in the sense that they work, but neither address the actual problem with the code you supplied.
The problem is that data is defined as:
data = {'chat_id', chat_id}
which is a set (not a dictionary) with two values: a string 'chat_id' and the content of chat_id, instead of
data = {'chat_id' : chat_id}
which is a dictionary with a key: the string 'chat_id' and a corresponding value stored in chat_id.
chat_id can be defined as part of the url, but similarly your original code should work as well - defining data and files as parameters for requests.post() - as long as both data and files variables are dictionaries.

You need to pass chat_id parameter in URL:
files = {'photo': open('./saved/{}.jpg'.format(user_id), 'rb')}
status = requests.post('https://api.telegram.org/bot<TOKEN>/sendPhoto?chat_id={}'.format(chat_id), files=files)

Your problem already solved by aiogram python framework.
This is full example. Just edit TOKEN and PHOTO_PATH, run the code and send /photo command to the bot :)
from aiogram import Bot, Dispatcher, executor
from aiogram.types import InputFile, Message
TOKEN = "YourBotToken"
PHOTO_PATH = "img/photo.png"
bot = Bot(TOKEN)
dp = Dispatcher(bot)
#dp.message_handler(commands=["photo"])
async def your_command_handler(message: Message):
photo = InputFile(PHOTO_PATH)
await message.answer_photo(photo)
if __name__ == '__main__':
executor.start_polling(dp)

Related

How to include an emoji in the document filename sent to a user using the Telegram Bot Api?

Consider this file with arbitrary content:
diamond💎.txt
When I browse my telegram application select the above file and send it to one of my contacts they get the file with the same name as above (diamond emoji included).
But when I try to send the same file through bot API they get it shown without diamond emoji. They see:
diamond.txt
I have tried to encode the string as 'utf-8', 'ascii' and even url encode but none works.
The code I use:
import json
import requests
import urllib
def sendoc(token, chid, pathtodoc, caption:str=None, repkey:dict=None):
URL = 'https://api.telegram.org/bot{}/'.format(token) # Telegram bot API url + TOKEN
data = {'chat_id': chid}
data['caption'] = caption
if repkey:
replykey = json.dumps(repkey)
data['reply_markup'] =replykey
files = {'document': (pathtodoc, open(pathtodoc, 'rb'))}
resp = requests.post(URL + 'sendDocument', files = files, data = data)
resp = resp.json()
return resp
token = "your bot token"
chid = -1000923413394 # example chat id
pathtodoc = './diamond💎.txt'
ret = sendoc(token, chid, pathtodoc)
print(ret)
Please help me to send emoji within filename from Bot api.
UPDATE:
I find out that there are many other people experiencing similar issue with sending files with non ascii filename through requests module.
See here, here and here.

Exporting specific json data from api with python

First time here, I am making a small discord.py bot as a project to experiment with python/apis a little. My goal is to print in discord specific data from an api when asked. here is the code in question.
#client.command()
async def otherusers(ctx, player):
rs = requests.get(apiLink + "/checkban?name=" + str(player))
if rs.status_code == 200:
rs = rs.json()
embed = discord.Embed(title="Other users for" + str(player), description="""User is known as: """ + str(rs["usedNames"]))
await ctx.send(embed=embed)
here is an example of the API request
{"id":1536171865,"avatar":"https://secure.download.dm.origin.com/production/avatar/prod/userAvatar/41472001/208x208.PNG","name":"_7cV","vban":{"A1 Army of One":{"bannedUntil":null,"reason":"ping >1000"}},"ingame":[],"otherNames":{"updateTimestamp":"2022-07-08T10:10:50.939000","usedNames":["ABCDE123","ABCDE1234","ABCDE12345","ABCDE1234567"]}}
If I change the string to str(rs["otherNames"]) it does function but I would like to only include the usernames, if I put str(rs["usedNames"]) and request on discord it gives me an error on PyCharm.
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: KeyError: 'usedNames'
Thanks in advance :)
Alright so as far as I can tell, the return from your API request where the "usedNames" key is located is nested. Try:
str(rs["otherNames"]["usedNames"])
I should note this will return ["ABCDE123","ABCDE1234","ABCDE12345","ABCDE1234567"] in the example which you gave. You might want to format the list of other usernames for your final product.
I hope that helped:)

Discord - Send messages from a channel to my website in real time

I currently have a python/django platform and a discord community. On my discord server there is a channel "announcements". I would just like that when a message is published in this channel, it goes up to my website in real time. This is in order to convert it into a notification.
Currently I managed to upload the messages from the channel to my site in a simple way but not in real time:
def discord_get_last_message_id():
message_id = 0
try:
message_id = Notification.objects.latest('id').discord_message_id
except:
pass
return message_id
def get_channel_messages():
#load last id discord message in DB
last_message_id = discord_get_last_message_id()
#Base route
route = "/channels/"+ DISCORD_CHANNEL_ANNONCES_ID +"/messages"
#if first time to DB, load just one item
if last_message_id == 0:
add = "?limit=1"
else:
add = "?after="+last_message_id
route = route + add
data,error_message = request_discord('GET',route)
print(data)
def request_discord(method,url_access,body={}):
data =''
#Call token
error_message = ''
access_token = discord_get_token()
#Call request
headers = {'Authorization': access_token}
body = body
if method=="GET":
result = requests.get(DISCORD_BASE_URI + url_access, headers=headers)
else:
result = requests.post(DISCORD_BASE_URI + url_access, headers=headers,data=body)
#Check result
if result.status_code != 200 and result.status_code != 201:
error_message = "Impossible de d'obtenir un resultat erreur: " + str(result.status_code)
else:
data = result.json()
return data,error_message
def discord_get_token():
return DISCORD_ANNONCES_CHANNEL_TOKEN
I'm trying to understand how discord websockets work but I have the impression that it's made to communicate with a bot only.
My question is, which way should I go to get the messages from my discord channel to my website in real time? Do I have to go through a bot?
NOTE: the goal is to get his messages to make notifications on my platform.
Thanks for your answers !
To answer your question:
My question is, which way should I go to get the messages from my discord channel to my website in real time? Do I have to go through a bot?
The best way would be to use a bot. This is the simplest, yet best way to do accomplish what you want. You could use a on_message event to get messages when they are sent. Then you could use that message and update your website. An example of how to do this is:
#bot.event
async def on_message(message):
message_content = message.content
return
You can do whatever you want with message_content. For your purpose you might want to store it in a database.
For the website side, you could use JavaScript to get the messages from the DB and update the HTML accordingly.

Posting a message in Symphony from Python

I'm trying to send a message from Symphony using Python.
https://developers.symphony.com/restapi/reference#create-message-v4
I found this page but I don't really know how to use it ( There's a cURL and a post url .. ) and I don't understand how I can use requests in this context ( still a beginner in API ).
Can someone help me to figure out how I can use this page to send a message from Python.
Thank you
You have to pass some required things in headers and use multipart/from-data content-type.
If you know about the postman then first with that and pass required headers.
files ={"message":"<messageML>Hello world!</messageML>"}
headers={
"sessionToken": "SESSION_TOKEN",
"keyManagerToken": "KEY_MANAGER_TOKEN"
}
requests.post("https://YOUR-AGENT-URL.symphony.com/agent/v4/stream/:sid/message/create", files=files,headers=headers)
https://github.com/finos/symphony-bdk-python/blob/main/examples has alot of examples on how to use symphony sdk. From python you don't want to use the api. This is the simple code to send a message from a bot. If you do not have a bot set up yet, follow https://docs.developers.symphony.com/building-bots-on-symphony/configuration/configure-your-bot-for-bdk-2.0-for-python NOTE you will need an admin user to follow these steps.
from symphony.bdk.core.config.loader import BdkConfigLoader
from symphony.bdk.core.symphony_bdk import SymphonyBdk
config = BdkConfigLoader.load_from_file("config.yaml")
async with SymphonyBdk(config) as bdk:
streams = bdk.streams()
messages = bdk.messages()
user_id = 123 # this can be found by clicking on a profile and copy profile link eg symphony://?userId=31123123123
stream = await streams.create_im_or_mim([user_id])
await messages.send_message(stream.id, f"<messageML>Message you want to send</messageML>")

Send text message via python to the Telegram Bot

I have been trying since the morning but earlier there were errors, so i had the direction but now there is no error and even not a warning too..
How code looks like :
import requests
def send_msg(text):
token = "TOKEN"
chat_id = "CHATID"
url_req = "https://api.telegram.org/bot" + token + "/sendMessage" + "?chat_id=" + chat_id + "&text=" + text
results = requests.get(url_req)
print(results.json())
send_msg("hi there 1234")
What is expected output :
It should send a text message
What is the current output :
It prints nothing
It would be great help is someone helps, Thank you all
Edit : 2
As the below dependancies were not installed, it was not capable of sending the text .
$ pip install flask
$ pip install python-telegram-bot
$ pip install requests
Now can somebody help me with sendPhoto please? I think it is not capable of sending image via URL, Thank you all
**Edit 3 **
I found a image or video sharing url from here but mine image is local one and not from the remote server
There is nothing wrong with your code. All you need to do is proper indentation.
This error primarily occurs because there are space or tab errors in
your code. Since Python uses procedural language, you may experience
this error if you have not placed the tabs/spaces correctly.
Run the below code. It will work fine :
import requests
def send_msg(text):
token = "your_token"
chat_id = "your_chatId"
url_req = "https://api.telegram.org/bot" + token + "/sendMessage" + "?chat_id=" + chat_id + "&text=" + text
results = requests.get(url_req)
print(results.json())
send_msg("Hello there!")
To send a picture might be easier using bot library : bot.sendPhoto(chat_id, 'URL')
Note : It's a good idea to configure your editor to make tabs and spaces visible to avoid such errors.
This works for me:
import telegram
#token that can be generated talking with #BotFather on telegram
my_token = ''
def send(msg, chat_id, token=my_token):
"""
Send a mensage to a telegram user specified on chatId
chat_id must be a number!
"""
bot = telegram.Bot(token=token)
bot.sendMessage(chat_id=chat_id, text=msg)
Here is an example that correctly encoded URL parameters using the popular requests library. This is a simple method if you simply want to send out plain-text or Markdown-formatted alert messages.
import requests
def send_message(text):
token = config.TELEGRAM_API_KEY
chat_id = config.TELEGRAM_CHAT_ID
url = f"https://api.telegram.org/bot{token}/sendMessage"
params = {
"chat_id": chat_id,
"text": text,
}
resp = requests.get(url, params=params)
# Throw an exception if Telegram API fails
resp.raise_for_status()
For full example and more information on how to set up a Telegram bot for a group chat, see README here.
Below is also the same using asyncio and aiohttp client, with throttling the messages by catching HTTP code 429. Telegram will kick out the bot if you do not throttle correctly.
import asyncio
import logging
import aiohttp
from order_book_recorder import config
logger = logging.getLogger(__name__)
def is_enabled() -> bool:
return config.TELEGRAM_CHAT_ID and config.TELEGRAM_API_KEY
async def send_message(text, throttle_delay=3.0):
token = config.TELEGRAM_API_KEY
chat_id = config.TELEGRAM_CHAT_ID
url = f"https://api.telegram.org/bot{token}/sendMessage"
params = {
"chat_id": chat_id,
"text": text,
}
attempts = 10
while attempts >= 0:
async with aiohttp.ClientSession() as session:
async with session.get(url, params=params) as resp:
if resp.status == 200:
return
elif resp.status == 429:
logger.warning("Throttling Telegram, attempts %d", attempts)
attempts -= 1
await asyncio.sleep(throttle_delay)
continue
else:
logger.error("Got Telegram response: %s", resp)
raise RuntimeError(f"Bad HTTP response: {resp}")

Categories