telega/deep_link

Deep-linking helpers: build t.me links that open the bot with a /start payload and read that payload back in the command handler.

Telegram restricts start payloads to A-Za-z0-9_-, at most 64 characters. To carry arbitrary data (user ids, referral codes with separators, unicode), pair encode_payload/decode_payload — they wrap the data in URL-safe base64, which fits the allowed alphabet.

// Somewhere a link is generated:
let assert Ok(link) = deep_link.encoded_start_link_for_bot(ctx.bot_info, "ref:42")
// -> "https://t.me/my_bot?start=cmVmOjQy"

// In the /start handler:
fn start_handler(ctx, command: update.Command) {
  case deep_link.decoded_payload_from_command(command) {
    Ok(Some(data)) -> reply.with_text(ctx, "Referred by: " <> data)
    _ -> reply.with_text(ctx, "Hello!")
  }
}

Types

pub type DeepLinkError {
  PayloadTooLong(actual: Int)
  InvalidPayloadCharacters(payload: String)
  MissingBotUsername
}

Constructors

  • PayloadTooLong(actual: Int)

    Payload (or data passed to encode_payload) exceeds the Telegram limit; actual is the offending length.

  • InvalidPayloadCharacters(payload: String)

    Payload is empty or contains characters outside A-Za-z0-9_-, or cannot be decoded back from base64.

  • MissingBotUsername

    The bot has no username, so no t.me link can be built.

Values

pub fn decode_payload(
  payload payload: String,
) -> Result(String, DeepLinkError)

Decodes a payload produced by encode_payload back to the original data.

pub fn decoded_payload_from_command(
  command command: update.Command,
) -> Result(option.Option(String), DeepLinkError)

Extracts and base64-decodes the payload of a command produced by an encode_payload-built link. Ok(None) means there was no payload.

pub fn encode_payload(
  data data: String,
) -> Result(String, DeepLinkError)

Encodes arbitrary data into a payload that fits the Telegram alphabet (URL-safe base64 without padding). Data must be at most 48 bytes, otherwise the encoded payload would not fit into 64 characters.

pub fn encoded_start_group_link(
  username username: String,
  data data: String,
) -> Result(String, DeepLinkError)

Like start_group_link, but encodes arbitrary data with encode_payload first.

pub fn encoded_start_group_link_for_bot(
  bot_info bot_info: types.User,
  data data: String,
) -> Result(String, DeepLinkError)

Encodes arbitrary data and builds a group start link for the bot.

pub fn encoded_start_link(
  username username: String,
  data data: String,
) -> Result(String, DeepLinkError)

Like start_link, but encodes arbitrary data with encode_payload first — one call instead of encode + link.

pub fn encoded_start_link_for_bot(
  bot_info bot_info: types.User,
  data data: String,
) -> Result(String, DeepLinkError)

Encodes arbitrary data and builds a start link for the bot — the closest analog of aiogram’s create_start_link(bot, data, encode=True):

let assert Ok(link) = deep_link.encoded_start_link_for_bot(ctx.bot_info, "ref:42")
pub const max_data_length: Int

Raw data longer than 48 bytes does not fit into 64 characters once base64-encoded.

pub const max_payload_length: Int

Telegram allows at most 64 characters in a start payload.

pub fn payload_from_command(
  command command: update.Command,
) -> option.Option(String)

Extracts the raw /start payload from a command, normalizing the empty payload of a bare /start to None.

pub fn start_app_link(
  username username: String,
  app_name app_name: String,
  payload payload: option.Option(String),
) -> Result(String, DeepLinkError)

Builds https://t.me/<username>/<app_name>?startapp=<payload> — opens a Mini App directly. Without a payload the startapp parameter is omitted.

pub fn start_app_link_for_bot(
  bot_info bot_info: types.User,
  app_name app_name: String,
  payload payload: option.Option(String),
) -> Result(String, DeepLinkError)

Like start_app_link, but takes the bot’s User (e.g. ctx.bot_info).

pub fn start_group_link(
  username username: String,
  payload payload: String,
) -> Result(String, DeepLinkError)

Builds https://t.me/<username>?startgroup=<payload> — prompts the user to pick a group to add the bot to; the payload arrives in /start.

pub fn start_group_link_for_bot(
  bot_info bot_info: types.User,
  payload payload: String,
) -> Result(String, DeepLinkError)

Like start_group_link, but takes the bot’s User (e.g. ctx.bot_info).

pub fn start_link(
  username username: String,
  payload payload: String,
) -> Result(String, DeepLinkError)

Builds https://t.me/<username>?start=<payload> — opens a private chat with the bot and suggests pressing Start; the payload arrives in the /start command. A leading @ in the username is ignored.

pub fn start_link_for_bot(
  bot_info bot_info: types.User,
  payload payload: String,
) -> Result(String, DeepLinkError)

Like start_link, but takes the bot’s User (e.g. ctx.bot_info) and fails with MissingBotUsername when the bot has no username.

pub fn validate_payload(
  payload payload: String,
) -> Result(String, DeepLinkError)

Checks that a payload matches the Telegram deep-linking rules: 1 to 64 characters from A-Za-z0-9_-. Returns the payload unchanged.

Search Document