Телеграмм бот для работы с изображениями

Рейтинг: 0Ответов: 1Опубликовано: 10.03.2023

Ребят, хочу сделать чтобы бот отсылал фотку обработанную в Pillow, однако получаю ошибку: "aiogram.utils.exceptions.BadRequest: There is no photo in the request" Подскажите, мне надо сохранить фото в памяти или в чем то еще ошибка.

handlers/main.py

from aiogram.dispatcher.filters import Command
from aiogram.types import ReplyKeyboardRemove
import re
from states.make_screen_states import make_screen_states
from dispatcher import dp, bot
from aiogram import types
from aiogram.types.input_file import InputFile

from main.main import DrawScreen

DrawScreen = DrawScreen()


@dp.message_handler(Command('make_screen'))
async def main(message: types.Message):
    await message.answer('Введите название пары, например "BTCUSDT": ')
    await make_screen_states.Q1.set()


@dp.message_handler(state=make_screen_states.Q1)
async def main(message: types.Message, state: FSMContext):
    answer = message.text
    if len(answer) > 10:
        await state.finish()
        await message.answer('Слишком большое название')
        await message.answer(f'Повторить попытку: /make_screen')
    else:
        await state.update_data(pair =answer)
        await message.answer('Введите тип, например "Long" или "Short"')
        await make_screen_states.next()



@dp.message_handler(state=make_screen_states.Q2)
async def main(message: types.Message, state: FSMContext):
    answer = message.text.lstrip().lower()
    if answer != 'long' and answer != "short":
        await state.finish()
        await message.answer(f'Ошибка, нужно ввести "Long" или "Short"')
        await message.answer(f'Повторить попытку: /make_screen')
    else:
        await state.update_data(type =answer)
        await message.answer('Введите размер плеча, например "20" ')
        await make_screen_states.next()



@dp.message_handler(state=make_screen_states.Q3)
async def main(message: types.Message, state: FSMContext):
    answer = message.text.lstrip().lower()
    if len(answer) > 5 or not(answer.isdigit()):
        await state.finish()
        await message.answer(f'Ошибка, плечо нужно выразить только числами. А также оно не должно быть слишком большое или маленькое')
        await message.answer(f'Повторить попытку: /make_screen')
    else:
        await state.update_data(leverage = answer)
        await message.answer('Введите цену входа(entry price), например "1566" ')
        await make_screen_states.next()

@dp.message_handler(state=make_screen_states.Q4)
async def main(message: types.Message, state: FSMContext):
    answer = message.text.lstrip().lower()
    if not(answer.isdigit()):
        await state.finish()
        await message.answer(f'Ошибка, цена должна состоять только из цифр')
        await message.answer(f'Повторить попытку: /make_screen')
    else:
        await state.update_data(entry_price =answer)
        await message.answer('Введите текущую цену(current price), например "2477" ')
        await make_screen_states.next()


@dp.message_handler(state=make_screen_states.Q5)
async def main(message: types.Message, state: FSMContext):
    answer = message.text.lstrip().lower()
    if not(answer.isdigit()):
        await state.finish()
        await message.answer(f'Ошибка, цена должна состоять только из цифр')
        await message.answer(f'Повторить попытку: /make_screen')
    else:
        await state.update_data(current_price =answer)
        data = await state.get_data()
        await state.finish()
        await message.answer(f'Подождите, чуток')
        image = DrawScreen.get_data(data, message.chat.id)
        #photo = InputFile(f"main/images/{message.chat.id}_image.jpg")
        await bot.send_photo(message.chat.id, image)
        #DrawScreen.delete_screen(message.chat.id)

main/main.py

from PIL import Image, ImageDraw, ImageFont
import os

class DrawScreen:

    def __init__(self):
        self.image = Image.open("main/images/image.png")
        self.leverage_font  = ImageFont.truetype("./fonts/Demo_Fonts/Fontspring-DEMO-neuevektor-a-book.otf",30)
        self.coin_font = ImageFont.truetype("main/fonts/DMCAPS.TTF",30)
        self.res_font = ImageFont.truetype("main/fonts/DMCAPS.TTF",95)
        self.prices = ImageFont.truetype("main/fonts/DMCAPS.TTF",35)
        self.percent = ImageFont.truetype("main/fonts/GolosText-Regular.ttf",95)
        self.srok_font = ImageFont.truetype("main/fonts/GenerischSans-SemiBold.ttf",30)
        self.green_color = (40,191,132,255)
        self.red_color = (221,77,108,255)
        self.orange_color = (212,174,9,255)
        self.sell_buy_font = ImageFont.truetype("main/fonts/FFNort-Regular.ttf",25)
        self.drawer = ImageDraw.Draw(self.image)


    def is_int(self,str):
        try:
            int(str)
            return True
        except ValueError:
            return False



    def get_data(self,data, user_id):
        coin_name = data['pair']
        type = data['type']
        leverage = (data['leverage']) + 'x'
        entry = (data['entry_price'])
        take = (data['current_price'])


        
        if type == 'long': 
            res = (float(take) - float(entry)) / (float(entry) / 100)

        else:
            res = (float(entry) - float(take)) / (float(entry) / 100)


        if len(str(res)) > 5:
            new_res = ''
            list = []
            for i in range(5):
                list.append(str(res)[i])
            
            if list[-1] == '.':
                list.pop(-1)
                   
            for i in list:
                new_res += i 
            res = new_res

        self.drawscreen(res, coin_name, leverage, entry, take, type, user_id)

    def drawscreen(self, res, coin_name, leverage, entry, take, type, user_id):

        #draw type
        if type == 'short':
            self.drawer.text((145, 185), "Продать", font=self.sell_buy_font, fill= self.red_color)
        elif type == 'long':
            self.drawer.text((145, 185), "Купить", font=self.sell_buy_font, fill= self.green_color)

        #draw leverage
        if len(str(leverage)) == 3:
            self.drawer.text((338, 182), leverage, font=self.leverage_font, fill='white')

        
        elif len(str(leverage)) == 4:
            self.drawer.text((334, 182), leverage, font=self.leverage_font, fill='white')

                
        elif len(str(leverage)) == 5:
            self.drawer.text((328, 182), leverage, font=self.leverage_font, fill='white')



        #draw coin_name 
        if len(str(coin_name)) == 6:
            self.drawer.text((450, 185), coin_name, font=self.coin_font, fill='white')
            self.drawer.text((570, 190), "Бессрочный", font=self.srok_font, fill='white')

        if len(str(coin_name)) == 7:
            self.drawer.text((450, 185), coin_name, font=self.coin_font, fill='white')
            self.drawer.text((590, 190), "Бессрочный", font=self.srok_font, fill='white')

        elif len(str(coin_name)) == 8:
            self.drawer.text((450, 185), coin_name, font=self.coin_font, fill='white')
            self.drawer.text((600, 190), "Бессрочный", font=self.srok_font, fill='white')

        elif len(str(coin_name)) == 9:
            self.drawer.text((450, 185), coin_name, font=self.coin_font, fill='white')
            self.drawer.text((610, 190), "Бессрочный", font=self.srok_font, fill='white')

        elif len(str(coin_name)) == 10:
            self.drawer.text((450, 185), coin_name, font=self.coin_font, fill='white')
            self.drawer.text((620, 190), "Бессрочный", font=self.srok_font, fill='white')

        #draw persent
        if len(str(res)) == 2:
            self.drawer.text((150, 220), f"+{res}", font=self.res_font, fill=self.green_color) 
            self.drawer.text((325, 215), "%", font=self.percent, fill=self.green_color) 

        elif len(str(res)) == 3:
            self.drawer.text((150, 220), f"+{res}", font=self.res_font, fill=self.green_color) 
            self.drawer.text((370, 215), "%", font=self.percent, fill=self.green_color) 

        elif len(str(res)) == 4:
            self.drawer.text((120, 220), f"+{res}", font=self.res_font, fill=self.green_color) 
            self.drawer.text((390, 215), "%", font=self.percent, fill=self.green_color) 

        elif len (str(res)) == 5:
            self.drawer.text((120, 220), f"+{res}", font=self.res_font, fill=self.green_color) 
            self.drawer.text((420, 215), "%", font=self.percent, fill=self.green_color) 





        #draw entry and take price
        self.drawer.text((410, 330), entry, font=self.prices, fill=self.orange_color) 
        self.drawer.text((410, 370), take, font=self.prices, fill=self.orange_color) 

        self.image = self.image.convert('RGB')
        return self.image

В общем суть ясна, бот задает вопросы, а потом генерирует картинку, вопрос только в том, как ее правильно отправить. Заранее спасибо

Ответы

▲ 0Принят

Как пример, надеюсь разберетесь что к чему.

from aiogram.types.input_file import InputFile
from PIL import Image
import io

def convert_to_grayscale(image_path="ozon.png"):
    img = Image.open(image_path).convert('L')

    buf = io.BytesIO()
    img.save(buf, format='png')
    buf.seek(0)
    return buf

@dp.message_handler(commands='convert')
async def convert(message: Message):
    buf = convert_to_grayscale()
    photo = InputFile(buf)
    await bot.send_photo(message.chat.id, photo)
    buf.close()