Перейти к содержанию

Deep Linking

maxapi.utils.deep_linking

Утилиты для создания и декодирования deep links MAX.

encode_payload(payload, encoder=None)

Кодирует payload в URL-safe base64 без padding.

Parameters:

Name Type Description Default
payload str | _SupportsStr

Payload. Значения не строкового типа приводятся к строке.

required
encoder Callable[[bytes], bytes] | None

Дополнительный кодировщик байтов.

None

Returns:

Type Description
str

Закодированный payload.

Source code in maxapi/utils/deep_linking.py
def encode_payload(
    payload: str | _SupportsStr,
    encoder: Callable[[bytes], bytes] | None = None,
) -> str:
    """
    Кодирует payload в URL-safe base64 без padding.

    Args:
        payload: Payload. Значения не строкового типа приводятся к строке.
        encoder: Дополнительный кодировщик байтов.

    Returns:
        Закодированный payload.
    """
    if not isinstance(payload, str):
        payload = str(payload)

    payload_bytes = payload.encode("utf-8")
    if encoder is not None:
        payload_bytes = encoder(payload_bytes)

    return base64.urlsafe_b64encode(payload_bytes).decode("ascii").rstrip("=")

decode_payload(payload, decoder=None)

Декодирует URL-safe base64 payload.

Parameters:

Name Type Description Default
payload str

Закодированный payload.

required
decoder Callable[[bytes], bytes] | None

Дополнительный декодировщик байтов.

None

Returns:

Type Description
str

Исходная строка payload.

Source code in maxapi/utils/deep_linking.py
def decode_payload(
    payload: str,
    decoder: Callable[[bytes], bytes] | None = None,
) -> str:
    """
    Декодирует URL-safe base64 payload.

    Args:
        payload: Закодированный payload.
        decoder: Дополнительный декодировщик байтов.

    Returns:
        Исходная строка payload.
    """
    if not isinstance(payload, str):
        raise TypeError("payload должен быть строкой")

    if BAD_PAYLOAD_PATTERN.search(payload):
        raise ValueError("payload должен быть в URL-safe base64 формате")

    padding_needed = (-len(payload)) % 4
    try:
        payload_bytes = base64.urlsafe_b64decode(
            (payload + "=" * padding_needed).encode("ascii")
        )
    except (binascii.Error, ValueError) as e:
        raise ValueError(
            "payload должен быть в URL-safe base64 формате"
        ) from e

    if decoder is not None:
        payload_bytes = decoder(payload_bytes)

    try:
        return payload_bytes.decode("utf-8")
    except UnicodeDecodeError as e:
        raise ValueError(
            "payload должен быть в URL-safe base64 формате"
        ) from e

Создаёт deep link для старта бота.

Parameters:

Name Type Description Default
username str

Username бота.

required
payload str | _SupportsStr

Данные, которые MAX передаст в BotStarted.payload. Значения не строкового типа приводятся к строке.

required
encode bool

Кодировать payload через URL-safe base64. При передаче encoder кодирование выполняется независимо от значения encode.

False
encoder Callable[[bytes], bytes] | None

Дополнительный кодировщик байтов.

None

Returns:

Type Description
str

Ссылка вида https://max.ru/?start=.

Source code in maxapi/utils/deep_linking.py
def create_start_link(
    username: str,
    payload: str | _SupportsStr,
    *,
    encode: bool = False,
    encoder: Callable[[bytes], bytes] | None = None,
) -> str:
    """
    Создаёт deep link для старта бота.

    Args:
        username: Username бота.
        payload: Данные, которые MAX передаст в BotStarted.payload.
            Значения не строкового типа приводятся к строке.
        encode: Кодировать payload через URL-safe base64. При передаче
            encoder кодирование выполняется независимо от значения encode.
        encoder: Дополнительный кодировщик байтов.

    Returns:
        Ссылка вида https://max.ru/<botName>?start=<payload>.
    """
    return create_deep_link(
        username=username,
        link_type="start",
        payload=payload,
        encode=encode,
        encoder=encoder,
    )

Создаёт deep link для мини-приложения MAX.

Parameters:

Name Type Description Default
username str

Username бота.

required
payload str | _SupportsStr | None

Данные для параметра startapp. Значения не строкового типа приводятся к строке. Если не передан, ссылка содержит параметр startapp без значения.

None
encode bool

Кодировать payload через URL-safe base64. При передаче encoder кодирование выполняется независимо от значения encode.

False
encoder Callable[[bytes], bytes] | None

Дополнительный кодировщик байтов.

None

Returns:

Name Type Description
str

Ссылка вида https://max.ru/?startapp= или

https str

//max.ru/?startapp без payload.

Source code in maxapi/utils/deep_linking.py
def create_startapp_link(
    username: str,
    payload: str | _SupportsStr | None = None,
    *,
    encode: bool = False,
    encoder: Callable[[bytes], bytes] | None = None,
) -> str:
    """
    Создаёт deep link для мини-приложения MAX.

    Args:
        username: Username бота.
        payload: Данные для параметра startapp. Значения не строкового типа
            приводятся к строке. Если не передан, ссылка содержит параметр
            startapp без значения.
        encode: Кодировать payload через URL-safe base64. При передаче
            encoder кодирование выполняется независимо от значения encode.
        encoder: Дополнительный кодировщик байтов.

    Returns:
        Ссылка вида https://max.ru/<botName>?startapp=<payload> или
        https://max.ru/<botName>?startapp без payload.
    """
    return create_deep_link(
        username=username,
        link_type="startapp",
        payload=payload,
        encode=encode,
        encoder=encoder,
    )
create_deep_link(
    username: str,
    link_type: Literal["start"],
    payload: str | _SupportsStr,
    *,
    encode: bool = False,
    encoder: Callable[[bytes], bytes] | None = None,
) -> str
create_deep_link(
    username: str,
    link_type: Literal["startapp"],
    payload: str | _SupportsStr | None = None,
    *,
    encode: bool = False,
    encoder: Callable[[bytes], bytes] | None = None,
) -> str

Создаёт deep link MAX.

Parameters:

Name Type Description Default
username str

Username бота.

required
link_type Literal['start', 'startapp']

Тип ссылки: start или startapp.

required
payload str | _SupportsStr | None

Данные для query-параметра. Значения не строкового типа приводятся к строке.

None
encode bool

Кодировать payload через URL-safe base64. При передаче encoder кодирование выполняется независимо от значения encode.

False
encoder Callable[[bytes], bytes] | None

Дополнительный кодировщик байтов.

None

Raises:

Type Description
ValueError

Если link_type, username или payload невалидны.

Returns:

Type Description
str

Deep link MAX.

Source code in maxapi/utils/deep_linking.py
def create_deep_link(
    username: str,
    link_type: Literal["start", "startapp"],
    payload: str | _SupportsStr | None = None,
    *,
    encode: bool = False,
    encoder: Callable[[bytes], bytes] | None = None,
) -> str:
    """
    Создаёт deep link MAX.

    Args:
        username: Username бота.
        link_type: Тип ссылки: start или startapp.
        payload: Данные для query-параметра. Значения не строкового типа
            приводятся к строке.
        encode: Кодировать payload через URL-safe base64. При передаче
            encoder кодирование выполняется независимо от значения encode.
        encoder: Дополнительный кодировщик байтов.

    Raises:
        ValueError: Если link_type, username или payload невалидны.

    Returns:
        Deep link MAX.
    """
    if link_type not in ("start", "startapp"):
        raise ValueError('link_type должен быть "start" или "startapp"')

    username = _normalize_username(username)
    if payload is None:
        if link_type == "start":
            raise ValueError("payload обязателен для start deep link")
        return f"{MAX_DEEPLINK_HOST}/{username}?{link_type}"

    if not isinstance(payload, str):
        payload = str(payload)

    if encode or encoder is not None:
        payload = encode_payload(payload, encoder=encoder)

    _validate_payload(payload, link_type)
    return f"{MAX_DEEPLINK_HOST}/{username}?{link_type}={payload}"

Пример

from maxapi import F, Router
from maxapi.types import BotStarted
from maxapi.utils.deep_linking import (
    create_start_link,
    decode_payload,
)

router = Router()

link = create_start_link("MyBot", "123456789", encode=True)


@router.bot_started(F.payload)
async def on_deep_link(event: BotStarted) -> None:
    user_id = decode_payload(event.payload)

В MAX payload из ссылки https://max.ru/<botName>?start=<payload> приходит в событие BotStarted.payload.