так, смотр, мне нужно сделать так, чтобы сообщение с кодом активации, "код активации получен" отправлось не как новое сообщенпие, а удалялось любое предыдыщее сообщение в чат боте и на его месте появлслось это сообщение, у меня уже есть такая функция в файле utils (safe_delete_message), но есть небольшая проблема, я так понимаю это из-за того, что я использую опертаивную память для хранения сообщений. когад я использую эту функцию, сообщение удаляется, появляется на его месте новое сообщенеи с кодом активации, но потом я хочу в этом сообщении, к примеру нажать на кнопки "Текущие активации" или "Заверишть активацию" и эьти едйствия происходят в предыдыщем сообщении, нужно это исправтиь

1. # /bot/handlers/activation.py

import asyncio
import logging
import time
from typing import Dict, Any
from aiogram import Dispatcher, types, F, Bot
from aiogram.utils.keyboard import InlineKeyboardBuilder
from aiogram.fsm.context import FSMContext

from ..data import get_user_api_key
from ..api import SmsHubAPI
from ..utils import safe_edit_or_send_message, safe_delete_message
from ..constants.services import SERVICE_DISPLAY_NAMES

logger = logging.getLogger(__name__)

# Глобальная переменная для активаций
user_activations: Dict[int, Dict[str, Dict[str, Any]]] = {}

async def current_activations_handler(callback_query: types.CallbackQuery, state: FSMContext):
    try:
        await callback_query.answer()
    except Exception as e:
        logger.warning(f"Не удалось ответить на callback_query: {e}")
        
    user_id = callback_query.from_user.id
    activations = user_activations.get(user_id, {})

    if not activations:
        keyboard = InlineKeyboardBuilder()
        keyboard.button(text="🔙 Назад", callback_data="back_to_main_menu")
        keyboard.adjust(1)
        await safe_edit_or_send_message(
            message=callback_query.message,
            new_text="У вас нет активных активаций.",
            state=state,
            reply_markup=keyboard.as_markup()
        )
        return

    keyboard = InlineKeyboardBuilder()
    for activation_id, data in activations.items():
        service_name = SERVICE_DISPLAY_NAMES.get(data['service'], data['service'])
        keyboard.button(
            text=f"{service_name} ({data['number']}) - {data['status']}",
            callback_data=f"manage_activation:{activation_id}"
        )
    keyboard.button(text="🔙 Назад", callback_data="back_to_main_menu")
    keyboard.adjust(1)

    await safe_edit_or_send_message(
        message=callback_query.message,
        new_text="Ваши текущие активации:",
        state=state,
        reply_markup=keyboard.as_markup()
    )

async def manage_activation_handler(callback_query: types.CallbackQuery, state: FSMContext):
    try:
        await callback_query.answer()
    except Exception as e:
        logger.warning(f"Не удалось ответить на callback_query: {e}")

    user_id = callback_query.from_user.id
    activation_id = callback_query.data.split(":")[1]
    activations = user_activations.get(user_id, {})
    activation = activations.get(activation_id)

    if not activation:
        await safe_edit_or_send_message(
            message=callback_query.message,
            new_text="Активация не найдена.",
            state=state,
            reply_markup=callback_query.message.reply_markup
        )
        return

    service_name = SERVICE_DISPLAY_NAMES.get(activation['service'], activation['service'])

    keyboard = InlineKeyboardBuilder()

    if activation['status'] == 'Ожидание SMS':
        keyboard.button(text="❌ Отменить активацию", callback_data=f"cancel_activation:{activation_id}")
    elif activation['status'].startswith('Код получен'):
        keyboard.button(text="📂 Текущие активации", callback_data="current_activations")
        keyboard.button(text="✅ Завершить активацию", callback_data=f"complete_activation:{activation_id}")
    elif activation['status'].startswith('Ожидание повторного SMS'):
        keyboard.button(text="✅ Завершить активацию", callback_data=f"complete_activation:{activation_id}")
    else:
        keyboard.button(text="✅ Завершить активацию", callback_data=f"complete_activation:{activation_id}")
        keyboard.button(text="❌ Отменить активацию", callback_data=f"cancel_activation:{activation_id}")
    
    keyboard.button(text="🔙 Назад", callback_data="current_activations")
    keyboard.adjust(1)

    await safe_edit_or_send_message(
        message=callback_query.message,
        new_text=(
            f"*Активация:* {activation_id}\n"
            f"*Сервис:* {service_name}\n"
            f"*Номер:* `{activation['number']}`\n"
            f"*Статус:* {activation['status']}"
        ),
        state=state,
        reply_markup=keyboard.as_markup(),
        parse_mode="Markdown"
    )

async def cancel_activation_handler(callback_query: types.CallbackQuery, state: FSMContext):
    try:
        await callback_query.answer()
    except Exception as e:
        logger.warning(f"Не удалось ответить на callback_query: {e}")
    
    user_id = callback_query.from_user.id
    activation_id = callback_query.data.split(":")[1]
    user_api_key = get_user_api_key(user_id)
    smshub_api = SmsHubAPI(user_api_key)

    activations = user_activations.get(user_id, {})
    activation = activations.get(activation_id)

    if activation:
        task = activation.get('task')
        if task:
            task.cancel()

        result = await smshub_api.cancel_activation(activation_id)
        logger.info(f"Активация {activation_id} отменена на стороне API: {result}")

        del activations[activation_id]

        keyboard = InlineKeyboardBuilder()
        keyboard.button(text="🔙 Назад", callback_data="current_activations")
        keyboard.adjust(1)

        await safe_edit_or_send_message(
            message=callback_query.message,
            new_text="Активация успешно отменена.",
            state=state,
            reply_markup=keyboard.as_markup()
        )
    else:
        await safe_edit_or_send_message(
            message=callback_query.message,
            new_text="Активация не найдена.",
            state=state,
            reply_markup=callback_query.message.reply_markup
        )

async def request_another_sms_handler(callback_query: types.CallbackQuery, state: FSMContext):
    try:
        await callback_query.answer()
    except Exception as e:
        logger.warning(f"Не удалось ответить на callback_query: {e}")

    user_id = callback_query.from_user.id
    activation_id = callback_query.data.split(":")[1]
    user_api_key = get_user_api_key(user_id)
    smshub_api = SmsHubAPI(user_api_key)
    activations = user_activations.get(user_id, {})
    activation = activations.get(activation_id)

    if not activation:
        await safe_edit_or_send_message(
            message=callback_query.message,
            new_text="Активация не найдена.",
            state=state,
            reply_markup=callback_query.message.reply_markup
        )
        return

    result = await smshub_api.set_status(activation_id, status="3")
    if result == "ACCESS_RETRY_GET":
        task = activation.get('task')
        if task:
            task.cancel()

        task = asyncio.create_task(poll_for_sms(
            bot=callback_query.message.bot,
            user_id=user_id,
            chat_id=callback_query.from_user.id,
            activation_id=activation_id,
            smshub_api=smshub_api
        ))
        activation['task'] = task
        activation['status'] = 'Ожидание повторного SMS'

        await safe_edit_or_send_message(
            message=callback_query.message,
            new_text="Запрошен повторный SMS. Ожидание SMS...",
            state=state,
            reply_markup=callback_query.message.reply_markup
        )
    else:
        logger.error(f"Не удалось запросить повторное SMS. Ответ: {result}")
        await safe_edit_or_send_message(
            message=callback_query.message,
            new_text="Не удалось запросить повторный SMS. Попробуйте снова.",
            state=state,
            reply_markup=callback_query.message.reply_markup
        )

async def complete_activation_handler(callback_query: types.CallbackQuery, state: FSMContext):
    try:
        await callback_query.answer()
    except Exception as e:
        logger.warning(f"Не удалось ответить на callback_query: {e}")

    user_id = callback_query.from_user.id
    activation_id = callback_query.data.split(":")[1]
    user_api_key = get_user_api_key(user_id)
    smshub_api = SmsHubAPI(user_api_key)
    activations = user_activations.get(user_id, {})
    activation = activations.get(activation_id)

    if not activation:
        await safe_edit_or_send_message(
            message=callback_query.message,
            new_text="Активация не найдена.",
            state=state,
            reply_markup=callback_query.message.reply_markup
        )
        return

    result = await smshub_api.set_status(activation_id, status="6")
    if result == "ACCESS_ACTIVATION":
        task = activation.get('task')
        if task:
            task.cancel()

        del activations[activation_id]

        keyboard = InlineKeyboardBuilder()
        keyboard.button(text="🔙 Назад", callback_data="current_activations")
        keyboard.adjust(1)

        await safe_edit_or_send_message(
            message=callback_query.message,
            new_text="Активация успешно завершена.",
            state=state,
            reply_markup=keyboard.as_markup()
        )
    else:
        logger.error(f"Не удалось завершить активацию. Ответ: {result}")
        await safe_edit_or_send_message(
            message=callback_query.message,
            new_text="Не удалось завершить активацию. Попробуйте снова.",
            state=state,
            reply_markup=callback_query.message.reply_markup
        )

async def poll_for_sms(bot: Bot, user_id: int, chat_id: int, activation_id: str, smshub_api: SmsHubAPI):
    activations = user_activations.get(user_id, {})
    activation = activations.get(activation_id)

    if not activation:
        logger.error(f"Активация {activation_id} не найдена для пользователя {user_id}.")
        return

    try:
        max_wait_time = 300
        poll_interval = 3
        elapsed_time = 0

        while elapsed_time < max_wait_time:
            await asyncio.sleep(poll_interval)
            elapsed_time += poll_interval

            status_response = await smshub_api.get_status(activation_id)
            if not status_response:
                logger.error("Нет ответа при запросе статуса активации.")
                await bot.send_message(chat_id, "Не удалось получить статус активации. Попробуйте позже.")
                return

            status_parts = status_response.split(":", 1)
            status = status_parts[0]

            if status in ["STATUS_WAIT_CODE", "STATUS_WAIT_RETRY"]:
                activation['last_update'] = time.time()
                continue

            elif status == "STATUS_CANCEL":
                await bot.send_message(chat_id, "Активация была отменена.")
                activation['status'] = 'Активация отменена'
                return

            elif status == "STATUS_OK":
                code = status_parts[1] if len(status_parts) > 1 else "Код не получен"
                activation['status'] = f'Код получен: {code}'
                activation['last_update'] = time.time()

                # Создаем инлайн-клавиатуру
                keyboard = InlineKeyboardBuilder()
                keyboard.button(text="📂 Текущие активации", callback_data="current_activations")
                keyboard.button(text="✅ Завершить активацию", callback_data=f"complete_activation:{activation_id}")
                keyboard.adjust(1)

                # Отправляем новое сообщение и сохраняем его message_id
                sent_message = await bot.send_message(
                    chat_id=chat_id,
                    text=f"Код активации для номера `{activation['number']}`: `{code}`",
                    reply_markup=keyboard.as_markup(),
                    parse_mode="Markdown"
                )
                
                # Сохраняем новое message_id
                activation['message_id'] = sent_message.message_id

                return

            else:
                activation['status'] = f'Неизвестный статус: {status}'
                await bot.send_message(chat_id, f"Неизвестный статус активации: {status}")
                return
    except asyncio.CancelledError:
        logger.info(f"Задача poll_for_sms для активации {activation_id} была отменена.")
    except Exception as e:
        logger.error(f"Ошибка в poll_for_sms: {e}")
        activation['status'] = 'Ошибка при получении SMS'
        await bot.send_message(chat_id, "Произошла ошибка при получении SMS.")

def register_activation_handlers(dp: Dispatcher):
    dp.callback_query.register(current_activations_handler, F.data == "current_activations")
    dp.callback_query.register(manage_activation_handler, F.data.startswith("manage_activation"))
    dp.callback_query.register(cancel_activation_handler, F.data.startswith("cancel_activation"))
    dp.callback_query.register(request_another_sms_handler, F.data.startswith("request_another_sms"))
    dp.callback_query.register(complete_activation_handler, F.data.startswith("complete_activation"))



2. # /bot/utils.py

import logging
import time
import aiohttp
from aiogram import Bot, types
from aiogram.exceptions import TelegramBadRequest
from aiogram.fsm.context import FSMContext
from aiogram import Dispatcher
from typing import Optional

logger = logging.getLogger(__name__)

EXCHANGE_RATE_API_URL = "https://api.exchangerate-api.com/v4/latest/USD"
USD_TO_RUB_RATE_TTL = 3600

_cached_usd_to_rub_rate: Optional[float] = None
_cached_usd_to_rub_rate_time: float = 0.0

async def get_usd_to_rub_rate() -> Optional[float]:
    global _cached_usd_to_rub_rate, _cached_usd_to_rub_rate_time
    now = time.time()
    if _cached_usd_to_rub_rate and (now - _cached_usd_to_rub_rate_time < USD_TO_RUB_RATE_TTL):
        return _cached_usd_to_rub_rate
    try:
        async with aiohttp.ClientSession() as session:
            async with session.get(EXCHANGE_RATE_API_URL) as response:
                data = await response.json()
                rate = data.get('rates', {}).get('RUB')
                if rate:
                    _cached_usd_to_rub_rate = rate
                    _cached_usd_to_rub_rate_time = now
                    return rate
                else:
                    logger.error("Курс RUB не найден в ответе.")
                    return None
    except Exception as e:
        logger.error(f"Ошибка при запросе курса валют: {e}")
        return None

async def safe_edit_or_send_message(
    message: types.Message,
    new_text: str,
    state: FSMContext,
    **kwargs
) -> Optional[types.Message]:
    data = await state.get_data()
    last_message_id = data.get('last_message_id')
    last_message_text = data.get('last_message_text')
    last_reply_markup = data.get('last_reply_markup')

    new_reply_markup = kwargs.get("reply_markup")

    if last_message_id and (last_message_text != new_text or last_reply_markup != new_reply_markup):
        try:
            sent_message = await message.bot.edit_message_text(
                new_text,
                chat_id=message.chat.id,
                message_id=last_message_id,
                **kwargs
            )
            await state.update_data(last_message_text=new_text, last_reply_markup=new_reply_markup)
            return sent_message
        except TelegramBadRequest as e:
            if "message can't be edited" in str(e).lower():
                logger.warning(f"Сообщение не может быть отредактировано: {e}. Пробуем отправить новое сообщение.")
            else:
                logger.error(f"Ошибка при редактировании сообщения: {e}")
        except Exception as e:
            logger.exception(f"Неожиданная ошибка при редактировании сообщения: {e}")

    if last_message_id:
        try:
            await message.bot.delete_message(chat_id=message.chat.id, message_id=last_message_id)
        except Exception as del_exc:
            logger.error(f"Не удалось удалить сообщение: {del_exc}")

    try:
        sent_message = await message.answer(new_text, **kwargs)
        await state.update_data(
            last_message_id=sent_message.message_id,
            last_message_text=new_text,
            last_reply_markup=new_reply_markup
        )
        return sent_message
    except Exception as e:
        logger.error(f"Не удалось отправить новое сообщение: {e}")
        return None

async def safe_delete_message(bot: Bot, chat_id: int, message_id: int) -> None:
    try:
        await bot.delete_message(chat_id=chat_id, message_id=message_id)
    except Exception as e:
        logger.error(f"Не удалось удалить сообщение: {e}")

async def on_startup(dispatcher: Dispatcher):
    logger.info("Бот успешно запущен.")