Как правильно сделать отправку картинок через callback в aiogram 3.x?
У меня есть код, который генерирует картинки
После чего они сохраняются у меня локально в папку, имя каждой картинки = callback_data
.png, имя папки =uid
, введенный юзером
Затем создаются кнопки, каждая из которых именуется своим именем, взятым из
словаря, который парсится с сайта (Имя картинки это key
, имя кнопки это value
).
callback_data
каждой картинки соответствует своему key
из словаря (от 1 до 8 картинок)
Пробовал через FSM перекидывать в callback
переменную uid
, благодаря чему всё работает как надо (выдает юзеру картинку), но уходит в рекурсию из-за того, что я не очищаю FSM state.clear()
. А если я очищаю, то у меня перестает работать callback
, т.к. не получает переменную uid. В итоге бот ломается, постоянно повторяя функцию character_card
Пробовал через sqlite заносить tg id и uid (который пишет юзер в чат), но оттуда в переменную не достать
Мне надо каким-то образом заставить работать callback по моей задумке, чтобы он выдавал конкретному юзеру конкретную картинку из конкретной папки по callback
Тут в основной код бота засунуты все функции для примера, чтоб понятно было что откуда куда
def get_some_kb(some_dict: dict) -> InlineKeyboardMarkup:
kb = InlineKeyboardBuilder()
for key, value in some_dict.items():
kb.button(text=value,
callback_data=f"{key}",
)
kb.adjust(2)
return kb.as_markup()
class Reg(StatesGroup):
name = State()
name1 = State()
name2 = State()
router = Router()
@router.message(Command('character'),
StateFilter(None)
)
async def enkanet(message: Message, state: FSMContext):
await state.set_state(Reg.name)
await message.answer('Напиши свой UID')
print("card request")
@router.message(
StateFilter(Reg.name)
)
async def character_card(message: Message,
state: FSMContext,
) -> None: # noqa: C901, D103
await state.update_data(name=message.text)
data = await state.get_data()
uid = data["name"]
tgid = message.from_user.id
cur.execute(f"INSERT INTO users (uid, tg_id) VALUES (({uid}), ({tgid}))")
db.commit()
await message.bot.send_chat_action(
chat_id=message.chat.id,
action=ChatAction.TYPING
)
async with starrailcard.Card(save=True, remove_logo=True) as card: #Генератор картинок
try:
await message.answer("ЖДИ\n\n\nСекунд 10~15")
await card.set_lang("ru")
data1 = await card.create(uid=uid, style=2, force_update=True)
result = errorz()
if result:
print("Something went WRONG")
return message.answer("Что-то пошло не так... Введите UID снова")
key_id = data1.get_charter()
kb = get_some_kb(key_id)
except StarRailCardError:
print("StarRailCardError")
return message.answer("Что-то пошло не так... Введите UID")
await message.answer(f"{uid}\n\nВыберите...", reply_markup=kb)
@router.callback_query()
async def send_generated_image(call: CallbackQuery, state: FSMContext) -> None:
await state.update_data(name=message.text)
data = await state.get_data()
uid = data["name"]
photo_file = FSInputFile(path=f"E:/papka/{uid}/{call.data}.png") #Здесь у каждого uid своя папка
await call.message.answer_photo(photo=photo_file)
Решил таким образом, всё работает по задумке, НО теперь проблема, что работает только когда юзер один единственный. Надо как-то каждому tg_id привязать свой uid при выдаче картинки, но при этом оставить UPDATE
. Я не знаю как это сделать
async def add(id, tgid):
info = cur.execute('SELECT * FROM users WHERE tg_id=?', (tgid, )).fetchone()
if info is None:
cur.execute(f"INSERT INTO users (uid, tg_id) VALUES (({id}), ({tgid}))")
db.commit()
else:
sqlite_update_query = f"""UPDATE users SET uid = {id} WHERE tg_id = {tgid}"""
cur.execute(sqlite_update_query)
db.commit()
if sq.OperationalError:
return
return
@router.message(
StateFilter(Reg.name)
)
async def character_card(message: Message,
state: FSMContext,
) -> None:
await state.update_data(name=message.text)
data = await state.get_data()
id = data["name"]
tgid = message.from_user.id
await tg.add(id=id, tgid=tgid)
#тут далее идет генерация картинки и отправка кнопок
@router.callback_query() #проблема вот здесь с рассинхроном tg_id и uid
async def send_generated_image(call: CallbackQuery):
uid = cur.execute("SELECT uid FROM users").fetchone()[0]
tgid1 = cur.execute("SELECT tg_id FROM users").fetchone()[0]
print(uid, tgid1)
path = 'E:/papka/' + f"{uid}/{call.data}" + '.png'
photo_file = FSInputFile(path=path)
await call.message.answer_photo(photo=photo_file)
Ответы (1 шт):
Решил своим способом
@router.callback_query()
async def send_generated_image(call: CallbackQuery):
tg_id = call.from_user.id
uid = cur.execute("SELECT uid FROM users WHERE tg_id = ?", (tg_id,)).fetchone()[0]
if call.data == "1205":
caption="текст"
await call.message.answer_photo(photo=
FSInputFile(
path=f"E:/papka/{uid}/1205.png"
), caption=caption)
print(uid, tg_id)
path = 'E:/papka/' + f"{uid}/{call.data}" + '.png'
photo_file = FSInputFile(path=path)
await call.message.answer_photo(photo=photo_file)