first commit

This commit is contained in:
2026-04-04 21:30:35 +07:00
commit d66041fa31
24 changed files with 503 additions and 0 deletions

View File

@@ -0,0 +1,57 @@
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