This commit is contained in:
2026-07-09 16:45:17 +03:00
parent 5c7a9710f3
commit da24ed8ba7
23 changed files with 1542 additions and 358 deletions

View File

@@ -28,6 +28,7 @@ class BotConfigSnapshot:
bot_terms_url: str
bot_support_ticket_link: str
payment_review_link: str
broadcast_results_link: str
bot_start_image_enabled: bool
bot_start_image_path: str
referral_enabled: bool
@@ -36,6 +37,7 @@ class BotConfigSnapshot:
payment_plans_raw: str
payment_product_plans_raw: str
payment_transfer_text: str
payment_success_text: str
payment_support_text: str
payment_plan_traffic_limit_gb: int
payment_plan_traffic_reset_period: str
@@ -52,6 +54,8 @@ class BotConfigSnapshot:
fallback_support_ticket_thread_id: int | None = None
fallback_payment_review_chat_id: int | None = None
fallback_payment_review_thread_id: int | None = None
fallback_broadcast_results_chat_id: int | None = None
fallback_broadcast_results_thread_id: int | None = None
@property
def bot_public_username_normalized(self) -> str:
@@ -245,6 +249,24 @@ class BotConfigSnapshot:
else self.fallback_payment_review_thread_id
)
@property
def broadcast_results_chat_id(self) -> int | None:
parsed_chat_id, _ = Settings._parse_private_topic_link(self.broadcast_results_link)
return (
parsed_chat_id
if parsed_chat_id is not None
else self.fallback_broadcast_results_chat_id
)
@property
def broadcast_results_message_thread_id(self) -> int | None:
_, parsed_thread_id = Settings._parse_private_topic_link(self.broadcast_results_link)
return (
parsed_thread_id
if parsed_thread_id is not None
else self.fallback_broadcast_results_thread_id
)
class StaticBotConfigService:
def __init__(self, settings: Settings) -> None:
@@ -258,6 +280,7 @@ class StaticBotConfigService:
bot_terms_url=self._settings.bot_terms_url,
bot_support_ticket_link=self._settings.bot_support_ticket_link,
payment_review_link=self._settings.payment_review_link,
broadcast_results_link=self._settings.broadcast_results_link,
bot_start_image_enabled=self._settings.bot_start_image_enabled,
bot_start_image_path=self._settings.bot_start_image_path,
referral_enabled=True,
@@ -266,6 +289,11 @@ class StaticBotConfigService:
payment_plans_raw=self._settings.payment_plans_raw,
payment_product_plans_raw=self._settings.payment_product_plans_raw,
payment_transfer_text=self._settings.payment_transfer_text,
payment_success_text=getattr(
self._settings,
"payment_success_text",
Settings.model_fields["payment_success_text"].default,
),
payment_support_text=self._settings.payment_support_text,
payment_plan_traffic_limit_gb=self._settings.payment_plan_traffic_limit_gb,
payment_plan_traffic_reset_period=self._settings.payment_plan_traffic_reset_period,
@@ -282,6 +310,8 @@ class StaticBotConfigService:
fallback_support_ticket_thread_id=self._settings.support_ticket_message_thread_id,
fallback_payment_review_chat_id=self._settings.payment_review_chat_id,
fallback_payment_review_thread_id=self._settings.payment_review_message_thread_id,
fallback_broadcast_results_chat_id=self._settings.broadcast_results_chat_id,
fallback_broadcast_results_thread_id=self._settings.broadcast_results_message_thread_id,
)
@@ -414,6 +444,14 @@ class BotConfigService(StaticBotConfigService):
description="Формат: `https://t.me/c/<chat>/<topic>/<message>`.",
placeholder="https://t.me/c/1234567890/56/57",
),
"broadcast_results_link": BotConfigFieldSpec(
key="broadcast_results_link",
label="Ссылка на ответы рассылок",
section="links",
prompt="Введите приватную ссылку на чат/топик, куда будут приходить ответы опросов. Для очистки отправьте `-`.",
description="Формат: `https://t.me/c/<chat>/<topic>/<message>`.",
placeholder="https://t.me/c/3646494169/67/68",
),
"payment_transfer_text": BotConfigFieldSpec(
key="payment_transfer_text",
label="Инструкция по оплате",
@@ -430,6 +468,14 @@ class BotConfigService(StaticBotConfigService):
description="Используется при отклонении оплаты и ошибках выдачи доступа.",
placeholder="Если оплата прошла, но доступ не выдался, напишите в поддержку.",
),
"payment_success_text": BotConfigFieldSpec(
key="payment_success_text",
label="Текст после покупки",
section="texts",
prompt="Введите текст, который бот добавит к сообщению со ссылкой после подтверждения оплаты.",
description="Показывается покупателю вместе со ссылкой на подписку после выдачи или продления доступа.",
placeholder="Доступ выдан. Сохраните ссылку и используйте её для подключения.",
),
"payment_internal_squad_uuids_raw": BotConfigFieldSpec(
key="payment_internal_squad_uuids_raw",
label="UUID внутренних групп",
@@ -533,6 +579,12 @@ class BotConfigService(StaticBotConfigService):
bot_terms_url=str(overrides.get("bot_terms_url", self._settings.bot_terms_url)),
bot_support_ticket_link=str(overrides.get("bot_support_ticket_link", self._settings.bot_support_ticket_link)),
payment_review_link=str(overrides.get("payment_review_link", self._settings.payment_review_link)),
broadcast_results_link=str(
overrides.get(
"broadcast_results_link",
self._settings.broadcast_results_link,
)
),
bot_start_image_enabled=self._parse_bool(
overrides.get("bot_start_image_enabled"),
default=self._settings.bot_start_image_enabled,
@@ -558,6 +610,16 @@ class BotConfigService(StaticBotConfigService):
)
),
payment_transfer_text=str(overrides.get("payment_transfer_text", self._settings.payment_transfer_text)),
payment_success_text=str(
overrides.get(
"payment_success_text",
getattr(
self._settings,
"payment_success_text",
Settings.model_fields["payment_success_text"].default,
),
)
),
payment_support_text=str(overrides.get("payment_support_text", self._settings.payment_support_text)),
payment_plan_traffic_limit_gb=self._parse_int(
overrides.get("payment_plan_traffic_limit_gb"),
@@ -610,6 +672,8 @@ class BotConfigService(StaticBotConfigService):
fallback_support_ticket_thread_id=self._settings.support_ticket_message_thread_id,
fallback_payment_review_chat_id=self._settings.payment_review_chat_id,
fallback_payment_review_thread_id=self._settings.payment_review_message_thread_id,
fallback_broadcast_results_chat_id=self._settings.broadcast_results_chat_id,
fallback_broadcast_results_thread_id=self._settings.broadcast_results_message_thread_id,
)
async def update_setting(
@@ -672,6 +736,7 @@ class BotConfigService(StaticBotConfigService):
"bot_terms_url",
"bot_support_ticket_link",
"payment_review_link",
"broadcast_results_link",
"bot_start_image_path",
"payment_product_plans_raw",
"payment_vpn_squad_uuids_raw",
@@ -703,7 +768,7 @@ class BotConfigService(StaticBotConfigService):
if key == "notification_check_interval_hours":
return f"{max(int(value or 6), 1)} ч"
if key in {"payment_transfer_text", "payment_support_text"}:
if key in {"payment_transfer_text", "payment_success_text", "payment_support_text"}:
return cls._compact_text(str(value), max_length=120)
return cls._compact_text(str(value))
@@ -732,6 +797,7 @@ class BotConfigService(StaticBotConfigService):
"bot_terms_url",
"bot_support_ticket_link",
"payment_review_link",
"broadcast_results_link",
"bot_start_image_path",
"payment_external_squad_uuid",
"payment_user_tag",
@@ -798,10 +864,11 @@ class BotConfigService(StaticBotConfigService):
"bot_terms_url",
"bot_support_ticket_link",
"payment_review_link",
"broadcast_results_link",
}:
return value
if key in {"payment_transfer_text", "payment_support_text"}:
if key in {"payment_transfer_text", "payment_success_text", "payment_support_text"}:
if not value:
raise ValueError("Текст не может быть пустым.")
return value[:4000]