keep back button in dialog window: single photo via DynamicMedia, media group via bot with caption

This commit is contained in:
2026-07-15 01:05:02 +03:00
parent 16e9d7f124
commit 504c454afb
4 changed files with 104 additions and 36 deletions
@@ -1,10 +1,13 @@
from aiogram import Bot from aiogram import Bot
from aiogram.enums import ContentType
from aiogram.types import Message, CallbackQuery, InputMediaPhoto from aiogram.types import Message, CallbackQuery, InputMediaPhoto
from aiogram.utils.markdown import html_decoration as hd from aiogram.utils.markdown import html_decoration as hd
from aiogram_dialog import Window, DialogManager from aiogram_dialog import Window, DialogManager
from aiogram_dialog.widgets.text import Format, Const from aiogram_dialog.widgets.text import Format, Const
from aiogram_dialog.widgets.kbd import Row, SwitchTo, Button, ScrollingGroup, Select, Group from aiogram_dialog.widgets.kbd import Row, SwitchTo, Button, ScrollingGroup, Select, Group
from aiogram_dialog.widgets.input import MessageInput from aiogram_dialog.widgets.input import MessageInput
from aiogram_dialog.widgets.media import DynamicMedia
from aiogram_dialog.api.entities.media import MediaAttachment, MediaId
from magic_filter import F from magic_filter import F
from dishka import FromDishka from dishka import FromDishka
from dishka.integrations.aiogram_dialog import inject from dishka.integrations.aiogram_dialog import inject
@@ -633,7 +636,7 @@ async def on_transaction_selected(
tx = await transactions_repository.get_transaction_by_id(int(item_id)) tx = await transactions_repository.get_transaction_by_id(int(item_id))
if tx: if tx:
photo_file_ids = HoursTransactionsRepository.get_photo_file_ids(tx) photo_file_ids = HoursTransactionsRepository.get_photo_file_ids(tx)
if photo_file_ids: if len(photo_file_ids) > 1:
operation = "Начислено" if tx.transaction_type == "increase" else "Списано" operation = "Начислено" if tx.transaction_type == "increase" else "Списано"
emoji = "+" if tx.transaction_type == "increase" else "" emoji = "+" if tx.transaction_type == "increase" else ""
msk_time = tx.created_at.astimezone(msk_now().tzinfo).replace(tzinfo=None) msk_time = tx.created_at.astimezone(msk_now().tzinfo).replace(tzinfo=None)
@@ -648,9 +651,6 @@ async def on_transaction_selected(
caption = f"📋 <b>Детали транзакции</b>\n\n⚙️ <b>Операция:</b> {operation}\n🔢 <b>Количество:</b> {emoji}<code>{tx.amount}</code> ч\n📅 <b>Дата:</b> {date_str}{remark_text}{admin_info}" caption = f"📋 <b>Детали транзакции</b>\n\n⚙️ <b>Операция:</b> {operation}\n🔢 <b>Количество:</b> {emoji}<code>{tx.amount}</code> ч\n📅 <b>Дата:</b> {date_str}{remark_text}{admin_info}"
bot: Bot = dialog_manager.middleware_data.get("bot") bot: Bot = dialog_manager.middleware_data.get("bot")
try: try:
if len(photo_file_ids) == 1:
await bot.send_photo(callback.message.chat.id, photo_file_ids[0], caption=caption)
else:
media = [InputMediaPhoto(media=fid, caption=caption if i == 0 else None) for i, fid in enumerate(photo_file_ids)] media = [InputMediaPhoto(media=fid, caption=caption if i == 0 else None) for i, fid in enumerate(photo_file_ids)]
await bot.send_media_group(callback.message.chat.id, media=media) await bot.send_media_group(callback.message.chat.id, media=media)
except Exception: except Exception:
@@ -669,12 +669,12 @@ async def get_transaction_detail_data(
tx_id = dialog_manager.dialog_data.get("selected_transaction_id") tx_id = dialog_manager.dialog_data.get("selected_transaction_id")
if not tx_id: if not tx_id:
return {"detail_content": "Ошибка: транзакция не выбрана"} return {"detail_content": "Ошибка: транзакция не выбрана", "photo_media": None, "has_multiple_photos": False}
tx = await transactions_repository.get_transaction_by_id(int(tx_id)) tx = await transactions_repository.get_transaction_by_id(int(tx_id))
if not tx: if not tx:
return {"detail_content": "Ошибка: транзакция не найдена"} return {"detail_content": "Ошибка: транзакция не найдена", "photo_media": None, "has_multiple_photos": False}
operation = "Начислено" if tx.transaction_type == "increase" else "Списано" operation = "Начислено" if tx.transaction_type == "increase" else "Списано"
emoji = "+" if tx.transaction_type == "increase" else "" emoji = "+" if tx.transaction_type == "increase" else ""
@@ -698,8 +698,24 @@ async def get_transaction_detail_data(
📅 <b>Дата:</b> {date_str}{remark_text}{admin_info} 📅 <b>Дата:</b> {date_str}{remark_text}{admin_info}
""" """
photo_file_ids = HoursTransactionsRepository.get_photo_file_ids(tx)
photo_media = None
has_multiple_photos = len(photo_file_ids) > 1
if photo_file_ids and not has_multiple_photos:
photo_media = MediaAttachment(
type=ContentType.PHOTO,
file_id=MediaId(file_id=photo_file_ids[0]),
)
if has_multiple_photos:
detail_content = ""
else:
detail_content = content
return { return {
"detail_content": content, "detail_content": detail_content,
"photo_media": photo_media,
"has_multiple_photos": has_multiple_photos,
} }
@@ -1125,6 +1141,7 @@ resident_history_window = Window(
) )
resident_history_detail_window = Window( resident_history_detail_window = Window(
DynamicMedia("photo_media"),
Format("{detail_content}"), Format("{detail_content}"),
SwitchTo( SwitchTo(
Const("◀️ К списку"), Const("◀️ К списку"),
@@ -1,12 +1,15 @@
import json import json
from aiogram import Bot from aiogram import Bot
from aiogram.enums import ContentType
from aiogram.exceptions import TelegramBadRequest, TelegramForbiddenError, TelegramRetryAfter from aiogram.exceptions import TelegramBadRequest, TelegramForbiddenError, TelegramRetryAfter
from aiogram.types import Message, CallbackQuery, InputMediaPhoto from aiogram.types import Message, CallbackQuery, InputMediaPhoto
from aiogram_dialog import Window, DialogManager from aiogram_dialog import Window, DialogManager
from aiogram_dialog.widgets.text import Format, Const from aiogram_dialog.widgets.text import Format, Const
from aiogram_dialog.widgets.kbd import SwitchTo, Button, ScrollingGroup, Select, Row, Group from aiogram_dialog.widgets.kbd import SwitchTo, Button, ScrollingGroup, Select, Row, Group
from aiogram_dialog.widgets.input import MessageInput from aiogram_dialog.widgets.input import MessageInput
from aiogram_dialog.widgets.media import DynamicMedia
from aiogram_dialog.api.entities.media import MediaAttachment, MediaId
from dishka import FromDishka from dishka import FromDishka
from dishka.integrations.aiogram_dialog import inject from dishka.integrations.aiogram_dialog import inject
@@ -514,7 +517,7 @@ async def on_room_transaction_selected(
tx = await transactions_repository.get_transaction_by_id(int(item_id)) tx = await transactions_repository.get_transaction_by_id(int(item_id))
if tx: if tx:
photo_file_ids = HoursTransactionsRepository.get_photo_file_ids(tx) photo_file_ids = HoursTransactionsRepository.get_photo_file_ids(tx)
if photo_file_ids: if len(photo_file_ids) > 1:
operation = "Начислено" if tx.transaction_type == "increase" else "Списано" operation = "Начислено" if tx.transaction_type == "increase" else "Списано"
emoji = "+" if tx.transaction_type == "increase" else "" emoji = "+" if tx.transaction_type == "increase" else ""
msk_time = tx.created_at.astimezone(msk_now().tzinfo).replace(tzinfo=None) msk_time = tx.created_at.astimezone(msk_now().tzinfo).replace(tzinfo=None)
@@ -529,9 +532,6 @@ async def on_room_transaction_selected(
caption = f"📋 <b>Детали транзакции</b>\n\n⚙️ <b>Операция:</b> {operation}\n🔢 <b>Количество:</b> {emoji}<code>{tx.amount}</code> ч\n📅 <b>Дата:</b> {date_str}{remark_text}{admin_info}" caption = f"📋 <b>Детали транзакции</b>\n\n⚙️ <b>Операция:</b> {operation}\n🔢 <b>Количество:</b> {emoji}<code>{tx.amount}</code> ч\n📅 <b>Дата:</b> {date_str}{remark_text}{admin_info}"
bot: Bot = dialog_manager.middleware_data.get("bot") bot: Bot = dialog_manager.middleware_data.get("bot")
try: try:
if len(photo_file_ids) == 1:
await bot.send_photo(callback.message.chat.id, photo_file_ids[0], caption=caption)
else:
media = [InputMediaPhoto(media=fid, caption=caption if i == 0 else None) for i, fid in enumerate(photo_file_ids)] media = [InputMediaPhoto(media=fid, caption=caption if i == 0 else None) for i, fid in enumerate(photo_file_ids)]
await bot.send_media_group(callback.message.chat.id, media=media) await bot.send_media_group(callback.message.chat.id, media=media)
except Exception: except Exception:
@@ -549,12 +549,12 @@ async def get_room_transaction_detail_data(
tx_id = dialog_manager.dialog_data.get("selected_transaction_id") tx_id = dialog_manager.dialog_data.get("selected_transaction_id")
if not tx_id: if not tx_id:
return {"detail_content": "Ошибка: транзакция не выбрана"} return {"detail_content": "Ошибка: транзакция не выбрана", "photo_media": None, "has_multiple_photos": False}
tx = await transactions_repository.get_transaction_by_id(int(tx_id)) tx = await transactions_repository.get_transaction_by_id(int(tx_id))
if not tx: if not tx:
return {"detail_content": "Ошибка: транзакция не найдена"} return {"detail_content": "Ошибка: транзакция не найдена", "photo_media": None, "has_multiple_photos": False}
operation = "Начислено" if tx.transaction_type == "increase" else "Списано" operation = "Начислено" if tx.transaction_type == "increase" else "Списано"
emoji = "+" if tx.transaction_type == "increase" else "" emoji = "+" if tx.transaction_type == "increase" else ""
@@ -578,8 +578,24 @@ async def get_room_transaction_detail_data(
📅 <b>Дата:</b> {date_str}{remark_text}{admin_info} 📅 <b>Дата:</b> {date_str}{remark_text}{admin_info}
""" """
photo_file_ids = HoursTransactionsRepository.get_photo_file_ids(tx)
photo_media = None
has_multiple_photos = len(photo_file_ids) > 1
if photo_file_ids and not has_multiple_photos:
photo_media = MediaAttachment(
type=ContentType.PHOTO,
file_id=MediaId(file_id=photo_file_ids[0]),
)
if has_multiple_photos:
detail_content = ""
else:
detail_content = content
return { return {
"detail_content": content, "detail_content": detail_content,
"photo_media": photo_media,
"has_multiple_photos": has_multiple_photos,
} }
@@ -822,6 +838,7 @@ room_history_window = Window(
) )
room_history_detail_window = Window( room_history_detail_window = Window(
DynamicMedia("photo_media"),
Format("{detail_content}"), Format("{detail_content}"),
SwitchTo( SwitchTo(
Const("◀️ К списку"), Const("◀️ К списку"),
@@ -1,10 +1,13 @@
import json import json
from aiogram import Bot from aiogram import Bot
from aiogram.enums import ContentType
from aiogram.types import CallbackQuery, InputMediaPhoto from aiogram.types import CallbackQuery, InputMediaPhoto
from aiogram_dialog import Window from aiogram_dialog import Window
from aiogram_dialog.widgets.text import Format, Const from aiogram_dialog.widgets.text import Format, Const
from aiogram_dialog.widgets.kbd import SwitchTo, ScrollingGroup, Select, Button from aiogram_dialog.widgets.kbd import SwitchTo, ScrollingGroup, Select, Button
from aiogram_dialog.widgets.media import DynamicMedia
from aiogram_dialog.api.entities.media import MediaAttachment, MediaId
from dishka import FromDishka from dishka import FromDishka
from dishka.integrations.aiogram_dialog import inject from dishka.integrations.aiogram_dialog import inject
@@ -83,7 +86,7 @@ async def on_creator_transaction_selected(
tx = await transactions_repository.get_transaction_by_id(int(item_id)) tx = await transactions_repository.get_transaction_by_id(int(item_id))
if tx: if tx:
photo_file_ids = HoursTransactionsRepository.get_photo_file_ids(tx) photo_file_ids = HoursTransactionsRepository.get_photo_file_ids(tx)
if photo_file_ids: if len(photo_file_ids) > 1:
operation = "Начислено" if tx.transaction_type == "increase" else "Списано" operation = "Начислено" if tx.transaction_type == "increase" else "Списано"
emoji = "+" if tx.transaction_type == "increase" else "" emoji = "+" if tx.transaction_type == "increase" else ""
room_mark = " 🚪" if tx.per_room else "" room_mark = " 🚪" if tx.per_room else ""
@@ -103,9 +106,6 @@ async def on_creator_transaction_selected(
caption = f"📋 <b>Детали транзакции</b>\n\n⚙️ <b>Операция:</b> {operation}\n🔢 <b>Количество:</b> {emoji}<code>{tx.amount}</code> ч{room_mark}\n👤 <b>Резидент:</b> {resident_name} (к. {room_number}){admin_info}\n📅 <b>Дата:</b> {date_str}{remark_text}" caption = f"📋 <b>Детали транзакции</b>\n\n⚙️ <b>Операция:</b> {operation}\n🔢 <b>Количество:</b> {emoji}<code>{tx.amount}</code> ч{room_mark}\n👤 <b>Резидент:</b> {resident_name} (к. {room_number}){admin_info}\n📅 <b>Дата:</b> {date_str}{remark_text}"
bot: Bot = dialog_manager.middleware_data.get("bot") bot: Bot = dialog_manager.middleware_data.get("bot")
try: try:
if len(photo_file_ids) == 1:
await bot.send_photo(callback.message.chat.id, photo_file_ids[0], caption=caption)
else:
media = [InputMediaPhoto(media=fid, caption=caption if i == 0 else None) for i, fid in enumerate(photo_file_ids)] media = [InputMediaPhoto(media=fid, caption=caption if i == 0 else None) for i, fid in enumerate(photo_file_ids)]
await bot.send_media_group(callback.message.chat.id, media=media) await bot.send_media_group(callback.message.chat.id, media=media)
except Exception: except Exception:
@@ -125,12 +125,12 @@ async def get_transaction_detail_data(
tx_id = dialog_manager.dialog_data.get("selected_transaction_id") tx_id = dialog_manager.dialog_data.get("selected_transaction_id")
if not tx_id: if not tx_id:
return {"detail_content": "Ошибка: транзакция не выбрана"} return {"detail_content": "Ошибка: транзакция не выбрана", "photo_media": None, "has_multiple_photos": False}
tx = await transactions_repository.get_transaction_by_id(int(tx_id)) tx = await transactions_repository.get_transaction_by_id(int(tx_id))
if not tx: if not tx:
return {"detail_content": "Ошибка: транзакция не найдена"} return {"detail_content": "Ошибка: транзакция не найдена", "photo_media": None, "has_multiple_photos": False}
operation = "Начислено" if tx.transaction_type == "increase" else "Списано" operation = "Начислено" if tx.transaction_type == "increase" else "Списано"
emoji = "+" if tx.transaction_type == "increase" else "" emoji = "+" if tx.transaction_type == "increase" else ""
@@ -162,8 +162,24 @@ async def get_transaction_detail_data(
📅 <b>Дата:</b> {date_str}{remark_text} 📅 <b>Дата:</b> {date_str}{remark_text}
""" """
photo_file_ids = HoursTransactionsRepository.get_photo_file_ids(tx)
photo_media = None
has_multiple_photos = len(photo_file_ids) > 1
if photo_file_ids and not has_multiple_photos:
photo_media = MediaAttachment(
type=ContentType.PHOTO,
file_id=MediaId(file_id=photo_file_ids[0]),
)
if has_multiple_photos:
detail_content = ""
else:
detail_content = content
return { return {
"detail_content": content, "detail_content": detail_content,
"photo_media": photo_media,
"has_multiple_photos": has_multiple_photos,
} }
@@ -192,6 +208,7 @@ transactions_history_window = Window(
) )
transactions_history_detail_window = Window( transactions_history_detail_window = Window(
DynamicMedia("photo_media"),
Format("{detail_content}"), Format("{detail_content}"),
SwitchTo( SwitchTo(
Const("◀️ К списку"), Const("◀️ К списку"),
@@ -1,8 +1,11 @@
from aiogram import Bot from aiogram import Bot
from aiogram.enums import ContentType
from aiogram.types import User, CallbackQuery, InputMediaPhoto from aiogram.types import User, CallbackQuery, InputMediaPhoto
from aiogram_dialog import Window from aiogram_dialog import Window
from aiogram_dialog.widgets.text import Format, Const from aiogram_dialog.widgets.text import Format, Const
from aiogram_dialog.widgets.kbd import Back, ScrollingGroup, Select, SwitchTo, Button from aiogram_dialog.widgets.kbd import Back, ScrollingGroup, Select, SwitchTo, Button
from aiogram_dialog.widgets.media import DynamicMedia
from aiogram_dialog.api.entities.media import MediaAttachment, MediaId
from dishka import FromDishka from dishka import FromDishka
from dishka.integrations.aiogram_dialog import inject from dishka.integrations.aiogram_dialog import inject
@@ -75,7 +78,7 @@ async def on_user_transaction_selected(
tx = await transactions_repository.get_transaction_by_id(int(item_id)) tx = await transactions_repository.get_transaction_by_id(int(item_id))
if tx: if tx:
photo_file_ids = HoursTransactionsRepository.get_photo_file_ids(tx) photo_file_ids = HoursTransactionsRepository.get_photo_file_ids(tx)
if photo_file_ids: if len(photo_file_ids) > 1:
operation = "Начислено" if tx.transaction_type == "increase" else "Списано" operation = "Начислено" if tx.transaction_type == "increase" else "Списано"
emoji = "+" if tx.transaction_type == "increase" else "" emoji = "+" if tx.transaction_type == "increase" else ""
msk_time = tx.created_at.astimezone(msk_now().tzinfo).replace(tzinfo=None) msk_time = tx.created_at.astimezone(msk_now().tzinfo).replace(tzinfo=None)
@@ -90,9 +93,6 @@ async def on_user_transaction_selected(
caption = f"📋 <b>Детали транзакции</b>\n\n⚙️ <b>Операция:</b> {operation}\n🔢 <b>Количество:</b> {emoji}<code>{tx.amount}</code> ч\n📅 <b>Дата:</b> {date_str}{remark_text}{admin_info}" caption = f"📋 <b>Детали транзакции</b>\n\n⚙️ <b>Операция:</b> {operation}\n🔢 <b>Количество:</b> {emoji}<code>{tx.amount}</code> ч\n📅 <b>Дата:</b> {date_str}{remark_text}{admin_info}"
bot: Bot = dialog_manager.middleware_data.get("bot") bot: Bot = dialog_manager.middleware_data.get("bot")
try: try:
if len(photo_file_ids) == 1:
await bot.send_photo(callback.message.chat.id, photo_file_ids[0], caption=caption)
else:
media = [InputMediaPhoto(media=fid, caption=caption if i == 0 else None) for i, fid in enumerate(photo_file_ids)] media = [InputMediaPhoto(media=fid, caption=caption if i == 0 else None) for i, fid in enumerate(photo_file_ids)]
await bot.send_media_group(callback.message.chat.id, media=media) await bot.send_media_group(callback.message.chat.id, media=media)
except Exception: except Exception:
@@ -112,12 +112,12 @@ async def get_history_detail_data(
tx_id = dialog_manager.dialog_data.get("selected_transaction_id") tx_id = dialog_manager.dialog_data.get("selected_transaction_id")
if not tx_id: if not tx_id:
return {"detail_content": "Ошибка: транзакция не выбрана"} return {"detail_content": "Ошибка: транзакция не выбрана", "photo_media": None, "has_multiple_photos": False}
tx = await transactions_repository.get_transaction_by_id(int(tx_id)) tx = await transactions_repository.get_transaction_by_id(int(tx_id))
if not tx: if not tx:
return {"detail_content": "Ошибка: транзакция не найдена"} return {"detail_content": "Ошибка: транзакция не найдена", "photo_media": None, "has_multiple_photos": False}
operation = "Начислено" if tx.transaction_type == "increase" else "Списано" operation = "Начислено" if tx.transaction_type == "increase" else "Списано"
emoji = "+" if tx.transaction_type == "increase" else "" emoji = "+" if tx.transaction_type == "increase" else ""
@@ -141,8 +141,24 @@ async def get_history_detail_data(
📅 <b>Дата:</b> {date_str}{remark_text}{admin_info} 📅 <b>Дата:</b> {date_str}{remark_text}{admin_info}
""" """
photo_file_ids = HoursTransactionsRepository.get_photo_file_ids(tx)
photo_media = None
has_multiple_photos = len(photo_file_ids) > 1
if photo_file_ids and not has_multiple_photos:
photo_media = MediaAttachment(
type=ContentType.PHOTO,
file_id=MediaId(file_id=photo_file_ids[0]),
)
if has_multiple_photos:
detail_content = ""
else:
detail_content = content
return { return {
"detail_content": content, "detail_content": detail_content,
"photo_media": photo_media,
"has_multiple_photos": has_multiple_photos,
} }
@@ -167,6 +183,7 @@ history_window = Window(
) )
history_detail_window = Window( history_detail_window = Window(
DynamicMedia("photo_media"),
Format("{detail_content}"), Format("{detail_content}"),
SwitchTo( SwitchTo(
Const("◀️ К списку"), Const("◀️ К списку"),