You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Python中为Telegram Bot发送的图片应用ForceReply并获取回复?

Fixing Telegram Bot ForceReply and Targeted Reply Retrieval Issues

Looks like you're hitting two common pitfalls with the Telegram Bot API—let's break them down and fix each one step by step.

1. Fixing the ForceReply Not Showing Up

Your current code has two key issues causing ForceReply to fail:

  • You’re passing 'ForceReply' as a raw string instead of the structured JSON object the API expects
  • You’re putting reply_markup in the files dictionary, but it belongs in form data (not part of the file upload payload)

The Telegram API requires reply_markup to be a JSON string defining the ForceReply configuration. Here's the corrected code to send your photo with working ForceReply:

import requests
import json

# Replace these with your actual values
UserID = "your_user_id_here"
BOT_API_TOKEN = "your_bot_token_here"
send_photo_url = f"https://api.telegram.org/bot{BOT_API_TOKEN}/sendPhoto"

# Build the ForceReply markup as a serialized JSON string
force_reply_markup = json.dumps({
    "force_reply": True,
    "selective": True  # Optional but recommended: only forces reply to this specific message
})

# Files only contains the photo file; other parameters go in the data dict
files = {'photo': open("/home/preetham/Downloads/selenium/cap.jpg", 'rb')}
data = {
    "chat_id": UserID,
    "reply_markup": force_reply_markup
}

# Send the request and capture the sent message's ID (we'll need this later)
status = requests.post(send_photo_url, files=files, data=data)
if status.ok:
    sent_photo_message_id = status.json()['result']['message_id']
    print(f"Photo sent successfully! Message ID: {sent_photo_message_id}")
else:
    print(f"Failed to send photo: {status.text}")

This will now properly trigger the "Reply" prompt tied directly to your sent photo.

2. Retrieving the Correct Reply to the Photo

Your polling code has two critical flaws:

  • It doesn’t use the offset parameter, so it keeps fetching old, already processed messages
  • It doesn’t verify if the reply is actually in response to your photo (it just grabs the last message in the history)

Here's the fixed polling logic that addresses both issues:

import time

get_updates_url = f"https://api.telegram.org/bot{BOT_API_TOKEN}/getUpdates"
offset = 0  # Tracks the last processed update to avoid re-reading old messages
reply_string = ""  # Variable to store the user's reply

while True:
    try:
        # Fetch only new updates using the offset parameter
        response = requests.get(get_updates_url, params={"offset": offset, "timeout": 30})
        response.raise_for_status()  # Throw an error if the API request fails
        updates = response.json()['result']
        
        for update in updates:
            update_id = update['update_id']
            # Update offset so we skip this update next time
            offset = update_id + 1
            
            # Check if this update is a message that's a reply to another message
            if 'message' in update and 'reply_to_message' in update['message']:
                incoming_message = update['message']
                # Verify the reply is targeting our sent photo
                if incoming_message['reply_to_message']['message_id'] == sent_photo_message_id:
                    # Ensure the reply is text (handle cases where user sends stickers/etc.)
                    if 'text' in incoming_message:
                        reply_string = incoming_message['text']
                        print(f"Received reply to your photo: {reply_string}")
                        exit()  # Exit loop once we get the correct reply
        
        time.sleep(1)  # Avoid hitting Telegram's API rate limits
    except Exception as e:
        print(f"Error fetching updates: {str(e)}")
        time.sleep(2)

Key Improvements:

  • Offset Management: By setting offset to update_id + 1, we tell the API to only send us updates we haven’t processed yet—no more old message repeats.
  • Reply Validation: We check that the message is a reply, and that it’s replying to the exact photo message we sent (matching the sent_photo_message_id we captured earlier).
  • Error Handling: Added basic error handling and rate limiting to make the polling more robust.

Quick Notes:

  • Fix the typo in your getUpdates URL: it should start with bot{BOT_API_TOKEN} (you missed the bot prefix and had a mismatched bracket).
  • Use requests.get for getUpdates instead of post—it’s the proper HTTP method for fetching data.

内容的提问来源于stack exchange,提问作者preethh

火山引擎 最新活动