Reputation: 23
I'm aware I can use this
client.send_file(receiver, '/path/to/photo.jpg')
to send an image, but how can I attach a caption to the image?
Upvotes: 2
Views: 4397
Reputation: 708
While this question on how to send an image with caption to Telegram using Telethon was already answered concisely by @matthew-barlowe, (which I used to come to my own solution, thank you), I felt that it would be helpful to include a more comprehensive example using Telethon v3's new async API.
The code is documented and type hinted so it should provide it's own explanation. In the interest of keeping the example brief, capturing of exceptions is excluded.
import logging
from random import uniform
from time import sleep
from typing import Dict, List, Union
from telethon.sync import TelegramClient
logging.basicConfig(
format="[%(levelname) 5s/%(asctime)s] %(name)s: %(message)s", level=logging.WARNING
)
# you should use dotenv module to extract credentials from the environment or .env file; 'pip install python-dotenv'
# do not store credentials in the file in production or git commit, this is only included for example purposes
SESSION_NAME = "sqlite-session"
TG_API_ID = 1234567890
TG_API_HASH = "*****"
CHANNEL_NAME = "yourchannelname"
CHANNEL_DISPLAY_NAME = "Your Channel Name"
CHANNEL_URL = "https://t.me/your-channel-name"
# define client
client = TelegramClient(SESSION_NAME, TG_API_ID, TG_API_HASH)
def create_message(data: Dict) -> str:
"""Formats a dictionary as a Telegram message.
:param data: Dict: A dictionary containing 'title', 'subtitle', 'text', 'url' and
'image_path' keys to be formatted as a message.
:return: str: A string including Markup to be sent as a message to a Telegram channel.
"""
# generate message
message = ""
if data.get("title", None):
message += f'**{data["title"]}**\n'
message += f'{data["subtitle"]}\n' if data.get("subtitle", None) else ""
if data.get("url", None):
message += data["url"]
message += "\n\n"
message += f"[{CHANNEL_DISPLAY_NAME}]({CHANNEL_URL})"
return message
async def channel_broadcast(
messages: Union[Dict, List[Dict]],
channel: str,
min_wait: float = 25.0,
max_wait: float = 120.0
) -> None:
""" Broadcasts a message to the specified Telegram channel. There will be a humanized wait in between postings.
:param messages: Union[Dict, List[Dict, ...]]: A dictionary or list of dicts containing 'title', 'subtitle',
'text', 'url' and 'image_path' keys to be formatted as a message.
:param channel: str: The name of the channel messages are to be broadcast to. You must have permission to
broadcast to this channel. See setup in telethon docs.
:param min_wait: float: Minimum wait between messages.
:param max_wait: float: Maximum wait between messages.
:return: None
"""
# ensure list
messages = [messages] if isinstance(messages, dict) else messages
for item in messages:
# generate a properly formatted message using markup and available fields
message = create_message(item)
# connect previously defined client
async with client:
await client.connect()
# send message if image is included
if item.get("image_path", None):
await client.send_file(
channel, item["image_path"], caption=message, link_preview=True
)
# send message without image
else:
await client.send_message(channel, message, link_preview=True)
# short blocking wait for multiple messages
# non-blocking waits are not in scope of this example
if len(messages) > 1:
sleep(uniform(min_wait, max_wait))
# you can provide a single dict or list of dicts
messages = [
{
"title": "First Message",
"subtitle": "This is the first message.",
"text": "This is a paragraph of text. The main idea of the message will be included here.",
"url": "https://test.com",
"image_path": "/path/to/a/local/image.png",
},
{
"title": "Second Message",
"subtitle": None,
"text": "This is a paragraph of text. The main idea of the message will be included here.",
"url": None,
},
]
# send all messages with a humanized wait between messages
with client:
client.loop.run_until_complete(
channel_broadcast(
messages, CHANNEL_NAME
)
)
'''
Upvotes: 1
Reputation: 2328
According to the documentation just pass the value of the caption with a keyword argument like so client.send_file(chat, '/my/photos/me.jpg', caption="It's me!")
. You can read the documentation here
Upvotes: 6