58 lines
1.7 KiB
Python
58 lines
1.7 KiB
Python
from typing import Protocol
|
|
|
|
from app.repositories.protocols import IUserRepository
|
|
|
|
|
|
class IReferralPayloadParser(Protocol):
|
|
"""Parse Telegram deep-link payload (e.g. `ref_ABC123`) into internal referrer key."""
|
|
|
|
def parse(self, raw: str | None) -> str | None: ...
|
|
|
|
|
|
class DefaultReferralPayloadParser:
|
|
"""Placeholder: expects `ref_<code>`; extend with signed tokens or DB lookup later."""
|
|
|
|
PREFIX = "ref_"
|
|
|
|
def parse(self, raw: str | None) -> str | None:
|
|
if not raw:
|
|
return None
|
|
if raw.startswith(self.PREFIX):
|
|
return raw[len(self.PREFIX) :].strip() or None
|
|
return None
|
|
|
|
|
|
class ReferralService:
|
|
"""
|
|
Resolves referral payloads to referrer user rows.
|
|
Placeholder: code is treated as referrer's telegram_id string for demo wiring;
|
|
replace with dedicated referral codes table or signed deep links in production.
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
users: IUserRepository,
|
|
parser: IReferralPayloadParser | None = None,
|
|
) -> None:
|
|
self._users = users
|
|
self._parser = parser or DefaultReferralPayloadParser()
|
|
|
|
async def resolve_referrer_id(
|
|
self,
|
|
start_payload: str | None,
|
|
*,
|
|
invitee_telegram_id: int,
|
|
) -> int | None:
|
|
code = self._parser.parse(start_payload)
|
|
if not code:
|
|
return None
|
|
# Placeholder: interpret code as referrer's telegram_id (digits only).
|
|
if not code.isdigit():
|
|
return None
|
|
referrer = await self._users.get_by_telegram_id(int(code))
|
|
if referrer is None:
|
|
return None
|
|
if referrer.telegram_id == invitee_telegram_id:
|
|
return None
|
|
return referrer.id
|