Отправить локальное фото из встроенного режима в бот телеграммы - PullRequest
1 голос
/ 29 марта 2020

Я использую Python бот Telegram API для своего бота.

Я хочу создавать фотографии локально и отправлять их как встроенные результаты, но InlineQueryResultPhoto принимает только URL-адреса фотографий.

Предположим, что структура моего проекта выглядит следующим образом:

main.py
photo.jpg

Как отправить photo.jpg в качестве встроенного результата?

Вот код 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()

1 Ответ

1 голос
/ 24 апреля 2020

Прямого ответа нет, потому что Telegram Bot API его не предоставляет. Но есть два обходных пути: вы можете использовать загрузку фотографии на серверы Telegram и затем использовать InlineQueryResultCachedPhoto или вы можете загрузить на любой сервер изображений и затем использовать InlineQueryResultPhoto.

InlineQueryResultCachedPhoto

This Первый вариант требует, чтобы вы предварительно загрузили фотографию на серверы Telegram перед созданием списка результатов. Какие варианты у вас есть? Бот может отправить вам фото, получить эту информацию и использовать то, что вам нужно. Другим вариантом является создание частного канала, где ваш бот может публиковать фотографии, которые он будет использовать повторно. Единственная деталь этого метода - узнать channel_id ( Как получить chat_id частного канала Telegram? ).

Теперь давайте посмотрим код:

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)

когда вы отправляете фотографию в чат / группу / канал, вы можете получить file_id, file_id миниатюры, подпись и другие подробности, которые я собираюсь пропустить. В чем проблема? Если вы не отфильтруете правильный запрос, вы можете отправить фотографию несколько раз на ваш личный канал. Это также означает, что автозаполнение не будет работать.

InlineQueryResultPhoto

Другой вариант - загрузить фотографию в inte rnet, а затем использовать URL-адрес. Исключая такие опции, как ваш собственный хостинг, вы можете использовать несколько бесплатных хостингов изображений, которые предоставляют API (например: imgur, imgbb). Для этого кода создание собственного ключа в imgbb проще, чем imgur. После генерации:

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)

Этот код похож на предыдущий метод (и включает в себя те же проблемы): загрузка несколько раз, если вы не фильтруете запрос и у вас не будет автозаполнения при записи inline.

Отказ от ответственности

Оба кода были написаны так, что изображения, которые вы хотите загрузить, генерируются в момент получения запроса, в противном случае вы можете выполнить работу, предшествующую получению запроса, сохранив эта информация в базе данных.

Бонус

Вы можете запустить своего собственного бота, чтобы получить channel_id вашего частного канала с помощью 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()

Чтобы получить идентификатор, который вам нужен написать в канале /getchannelid@botname

...