fix: isolate dev messages from production

This commit is contained in:
admin committed 2026-10-08 14:04:51 +02:00
1 parent 45b1c5b468
commit c02db5ada9
6 files changed
+124 -34

No files matched your search

+28 -17
View File
@@ -54,7 +54,7 @@ logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
VERSION = Path(__file__).with_name("VERSION").read_text(encoding="utf-8").strip()
BOT_ENV = os.getenv("BOT_ENV", "test").strip().lower()
DEPLOY_ENV = os.getenv("DEPLOY_ENV", "production").strip().lower()
DEPLOY_ENV = os.getenv("DEPLOY_ENV", "production")
DEV_CHAT_ID = os.getenv("DEV_CHAT_ID", "").strip()
HELP_COMMANDS = {"help", "помощь"}
_deploy_notice_lock = asyncio.Lock()
@@ -70,6 +70,11 @@ _deploy_notice_sent = False
_deploy_notice_lock = asyncio.Lock()
def is_development_environment() -> bool:
"""Enable developer-only behavior only for the explicit Coolify dev value."""
return DEPLOY_ENV == "development"
def _read_version() -> str:
version_path = Path(__file__).with_name("VERSION")
return version_path.read_text(encoding="utf-8").strip()
@@ -95,14 +100,19 @@ async def report_error(message: Message, stage: str, exc: Exception) -> None:
detail = re.sub(r"https?://\S+", "[внешний сервис]", detail)
detail = detail or "нет подробностей"
try:
await message.answer(f"❌ Не получилось: {stage}.\nПричина: <code>{html.escape(detail[:240])}</code>", parse_mode="HTML")
await message.answer(f"❌ Не получилось: {stage}. Попробуй ещё раз позже.")
if is_development_environment():
await message.answer(
f"🧪 Dev-диагностика: {stage}. Причина: <code>{html.escape(detail[:240])}</code>",
parse_mode="HTML",
)
except Exception as send_exc:
logger.error("Unable to report processing error: %s", type(send_exc).__name__)
logger.error("User operation failed at %s (%s): %s", stage, type(exc).__name__, detail[:240])
async def notify_development_deploy(bot: Bot) -> None:
if DEPLOY_ENV != "development":
if not is_development_environment():
return
chat_id = os.getenv("DEV_CHAT_ID", "").strip()
if not chat_id:
@@ -135,7 +145,7 @@ async def send_rich_message(message: Message, rich_html: str, stage: str) -> Mes
return sent
except Exception as exc:
logger.warning("Rich %s send failed (%s): %s", stage, type(exc).__name__, str(exc)[:180])
if DEPLOY_ENV == "development":
if is_development_environment():
await report_error(message, f"отправка Rich Message: {stage}", exc)
await message.answer(help_plain_view(None) if stage == "помощи" else rich_to_plain(rich_html))
return None
@@ -171,8 +181,8 @@ async def help_navigation(callback: CallbackQuery) -> None:
@router.callback_query(F.data.startswith("dev_paid:"))
async def confirm_development_payment(callback: CallbackQuery) -> None:
if DEPLOY_ENV != "development":
await callback.answer("Доступно только в dev-среде.", show_alert=True)
if not is_development_environment():
await callback.answer()
return
try:
user_id = int((callback.data or "").split(":", 1)[1])
@@ -184,7 +194,7 @@ async def confirm_development_payment(callback: CallbackQuery) -> None:
return
await asyncio.to_thread(ensure_subscription, user_id)
days = await asyncio.to_thread(user_store.activate_subscription, user_id, months=1)
await callback.answer("Dev-доступ активирован на 30 дней.")
await callback.answer()
if isinstance(callback.message, Message):
await callback.message.edit_reply_markup(reply_markup=None)
await callback.message.answer(
@@ -256,17 +266,19 @@ async def subscribe_command(message: Message) -> None:
)
except Exception as exc:
logger.error("Invoice send failed (%s): %s", type(exc).__name__, str(exc)[:180])
if DEPLOY_ENV == "development":
if is_development_environment():
await report_error(message, "отправка счёта на оплату", exc)
await message.answer(
"Не получилось открыть счёт на оплату. Попробуй ещё раз через минуту "
"или напиши поддержке."
)
else:
await message.answer(
"Не получилось открыть счёт на оплату. Попробуй ещё раз через минуту "
"или напиши поддержке."
)
return
if DEPLOY_ENV == "development":
await message.answer(f"Счёт на {SUBSCRIPTION_PRICE_STARS} звёзд на 30 дней выше.")
if is_development_environment():
await message.answer(
f"Счёт на {SUBSCRIPTION_PRICE_STARS} звёзд на 30 дней выше.\n\n"
"Для разработки нажми кнопку ниже: она включит dev-доступ без реального платежа.",
"🧪 Dev-режим: для продолжения разработки нажми кнопку ниже. "
"Она включит доступ без реального платежа.",
reply_markup=InlineKeyboardMarkup(
inline_keyboard=[[InlineKeyboardButton(
text="🧪 Оплатил (dev)",
@@ -276,7 +288,6 @@ async def subscribe_command(message: Message) -> None:
)
else:
await message.answer(
f"Счёт на {SUBSCRIPTION_PRICE_STARS} звёзд на 30 дней выше.\n\n"
"Подписка активируется сразу после оплаты — отдельного подтверждения не нужно."
)
@@ -311,7 +322,7 @@ async def clear_command(message: Message) -> None:
deactivate_subscription(message.from_user.id)
await message.answer(
"Команда /clear полностью обнулила твои данные: Tone of Voice, тексты со скриншотов, историю постов, историю идей и настройки. "
"API-логи для отладки сохранены. Пришли новые скриншоты, чтобы настроить стиль заново."
"Служебные API-логи сохраняются по установленному сроку хранения. Пришли новые скриншоты, чтобы настроить стиль заново."
)
await asyncio.sleep(0.5)
await message.answer(