feat: referral links now point to web cabinet instead of bot

Centralized referral link generation into settings.get_referral_link().
When CABINET_URL is configured, links use {CABINET_URL}?ref={code}.
Falls back to Telegram bot deep link when CABINET_URL is not set.

- URL-encodes referral_code for safety
- Handles CABINET_URL with existing query params (uses & vs ?)
- Guards against None referral_code in all call sites
- QR code caching uses link hash for auto-invalidation
This commit is contained in:
Fringg
2026-03-12 06:45:17 +03:00
parent 8a362db783
commit 12ae871653
4 changed files with 43 additions and 11 deletions
+1 -2
View File
@@ -92,8 +92,7 @@ async def get_referral_info(
available_balance = min(user.balance_kopeks, referral_entitlement)
# Build referral link
bot_username = settings.get_bot_username() or 'bot'
referral_link = f'https://t.me/{bot_username}?start={user.referral_code}'
referral_link = settings.get_referral_link(user.referral_code) if user.referral_code else ''
return ReferralInfoResponse(
referral_code=user.referral_code or '',
+20
View File
@@ -1415,6 +1415,26 @@ class Settings(BaseSettings):
return value
return None
_CABINET_URL_DEFAULT = 'https://example.com/cabinet'
def get_referral_link(self, referral_code: str, bot_username: str | None = None) -> str:
"""Build a referral link pointing to the web cabinet.
Falls back to a Telegram bot deep link when CABINET_URL is not configured.
"""
from urllib.parse import quote
if not referral_code:
raise ValueError('referral_code must not be empty or None')
safe_code = quote(referral_code, safe='')
cabinet_url = (self.CABINET_URL or '').strip().rstrip('/')
if cabinet_url and cabinet_url != self._CABINET_URL_DEFAULT:
sep = '&' if '?' in cabinet_url else '?'
return f'{cabinet_url}{sep}ref={safe_code}'
username = bot_username or self.get_bot_username() or 'bot'
return f'https://t.me/{username}?start={safe_code}'
def is_deep_links_enabled(self) -> bool:
return self.ENABLE_DEEP_LINKS
+20 -6
View File
@@ -1,3 +1,4 @@
import hashlib
import json
from pathlib import Path
@@ -37,10 +38,14 @@ async def show_referral_info(callback: types.CallbackQuery, db_user: User, db: A
texts = get_texts(db_user.language)
if not db_user.referral_code:
await callback.answer(texts.t('REFERRAL_CODE_NOT_ASSIGNED', 'Реферальный код не назначен'), show_alert=True)
return
summary = await get_user_referral_summary(db, db_user.id)
bot_username = (await callback.bot.get_me()).username
referral_link = f'https://t.me/{bot_username}?start={db_user.referral_code}'
referral_link = settings.get_referral_link(db_user.referral_code, bot_username)
referral_text = (
texts.t('REFERRAL_PROGRAM_TITLE', '👥 <b>Реферальная программа</b>')
@@ -229,17 +234,22 @@ async def show_referral_qr(
callback: types.CallbackQuery,
db_user: User,
):
await callback.answer()
texts = get_texts(db_user.language)
if not db_user.referral_code:
await callback.answer(texts.t('REFERRAL_CODE_NOT_ASSIGNED', 'Реферальный код не назначен'), show_alert=True)
return
await callback.answer()
bot_username = (await callback.bot.get_me()).username
referral_link = f'https://t.me/{bot_username}?start={db_user.referral_code}'
referral_link = settings.get_referral_link(db_user.referral_code, bot_username)
qr_dir = Path('data') / 'referral_qr'
qr_dir.mkdir(parents=True, exist_ok=True)
file_path = qr_dir / f'{db_user.id}.png'
link_hash = hashlib.md5(referral_link.encode()).hexdigest()[:8]
file_path = qr_dir / f'{db_user.id}_{link_hash}.png'
if not file_path.exists():
img = qrcode.make(referral_link)
img.save(file_path)
@@ -470,8 +480,12 @@ async def show_referral_analytics(callback: types.CallbackQuery, db_user: User,
async def create_invite_message(callback: types.CallbackQuery, db_user: User):
texts = get_texts(db_user.language)
if not db_user.referral_code:
await callback.answer(texts.t('REFERRAL_CODE_NOT_ASSIGNED', 'Реферальный код не назначен'), show_alert=True)
return
bot_username = (await callback.bot.get_me()).username
referral_link = f'https://t.me/{bot_username}?start={db_user.referral_code}'
referral_link = settings.get_referral_link(db_user.referral_code, bot_username)
invite_text = texts.t('REFERRAL_INVITE_TITLE', '🎉 Присоединяйся к VPN сервису!')
+2 -3
View File
@@ -2867,10 +2867,9 @@ async def _build_referral_info(
referral_code = getattr(user, 'referral_code', None)
referral_settings = settings.get_referral_settings() or {}
bot_username = settings.get_bot_username()
referral_link = None
if referral_code and bot_username:
referral_link = f'https://t.me/{bot_username}?start={referral_code}'
if referral_code:
referral_link = settings.get_referral_link(referral_code)
minimum_topup_kopeks = int(referral_settings.get('minimum_topup_kopeks') or 0)
first_topup_bonus_kopeks = int(referral_settings.get('first_topup_bonus_kopeks') or 0)