Documentation
¶
Overview ¶
Package convert maps gotd/td MTProto types to domain model types. All functions are pure: no I/O, no RPC, no side-effects. Spec: docs/design/phase-5-data/entity-mapping.md §Media Mapping Dispatch order: docs/design/phase-2-behavioral/media-rendering.md §Decision Tree
Package convert — names.go Shared helpers for resolving int64 user IDs against a names map.
Two contracts:
- LookupName: total predicate ((string, bool)). Caller decides fallback.
- ResolveName: convenience wrapper returning "Unknown" when missing.
Spec: docs/design/phase-5-data/entity-mapping.md §Name Resolution
Package convert — reactions.go Converts tg.MessageReactions → []model.Reaction (Step 25).
Design decisions (ADR-012 A1):
- tg.ReactionCustomEmoji entries are skipped (Step 25 scope).
- Output slice is sorted: Count desc, Emoji asc as tie-break.
- Snapshot semantics: caller replaces m.Reactions entirely.
Spec: docs/design/phase-5-data/entity-mapping.md §Reactions Mapping Invariant: REACTIONS_ORDERED (reactions.tla)
Package convert — service.go Formats tg.MessageActionClass → human-readable ServiceText string (Step 25).
Mapped variants: 12 common action types + "Service message" fallback. Totality invariant: every action, including unknown future variants, returns a non-empty string (no panic, no empty string).
Spec: docs/design/phase-5-data/entity-mapping.md §System Message Mapping Spec: docs/design/phase-2-behavioral/reactions-and-system.md §System Message Classification
Index ¶
- func ConvertFwdLabel(fwd *tg.MessageFwdHeader) string
- func ExtractLinks(msgText string, entities []tg.MessageEntityClass) []model.MessageLink
- func FlattenReactions(r tg.MessageReactions) []model.Reaction
- func FormatAction(action tg.MessageActionClass, names map[int64]string, actorID int64) string
- func LookupName(names map[int64]string, id int64) (string, bool)
- func ResolveName(names map[int64]string, id int64) string
- func SanitizeText(s string) string
- func ToMessageMedia(m tg.MessageMediaClass) *model.MessageMedia
- func Utf16Length(s string) int
- func Utf16Slice(text string, offset, length int) string
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ConvertFwdLabel ¶
func ConvertFwdLabel(fwd *tg.MessageFwdHeader) string
ConvertFwdLabel traduce tg.MessageFwdHeader nella stringa displayable per il campo model.Message.ForwardedFrom. Priorità implementata (ADR-021 §DC3):
- FromName esplicito (campo server-fornito, include username e nomi)
- PostAuthor per channel post firmati
- Fallback → "Hidden"
Invariante FORWARD_LABEL_FALLBACK_CHAIN: mai stringa vuota. Nota: FromID (priorità 1-3 del design) non è risolvibile senza user store; il server include già FromName nei forward visibili, quindi FromName è il punto di ingresso corretto. labelFromPeer era dead code (sempre "").
func ExtractLinks ¶
func ExtractLinks(msgText string, entities []tg.MessageEntityClass) []model.MessageLink
ExtractLinks converte le entity Telegram di un messaggio in []model.MessageLink. Invariante LINK_DETECTION_AUTHORITATIVE: usa solo tg.Message.Entities, mai regex. Solo MessageEntityURL e MessageEntityTextURL sono inclusi (ADR-021 §DB1). Offset/Length sono UTF-16 code units (Telegram MTProto spec) — usa Utf16Slice.
func FlattenReactions ¶
func FlattenReactions(r tg.MessageReactions) []model.Reaction
FlattenReactions converts a tg.MessageReactions snapshot to an ordered []model.Reaction slice. Returns nil if no standard emoji reactions exist.
Filtering rules:
- *tg.ReactionEmoji → included (standard emoji)
- *tg.ReactionCustomEmoji → skipped (premium; out of scope Step 25)
- *tg.ReactionEmpty → skipped (server placeholder)
Ordering: Count desc, then Emoji asc for deterministic tie-breaking. A non-deterministic ordering would cause render flicker when two reactions share the same count (REACTIONS_ORDERED invariant).
func FormatAction ¶
FormatAction converts a tg.MessageActionClass to a pre-formatted human-readable string. The names map resolves user IDs to display names; actorID is the message sender (used as fallback when the action does not embed a user ID).
ADR-012 B1: ServiceText is computed once at convert time (entities available in the MTProto response). Render-time lookup is avoided.
func LookupName ¶
LookupName reports whether id maps to a non-empty display name. Empty strings are treated as missing (defensive against partial entity data).
func ResolveName ¶
ResolveName returns the display name for id, or "Unknown" when absent. Use this when the caller has no domain-specific fallback to apply.
func SanitizeText ¶
SanitizeText rimuove control characters (< 0x20, == 0x7f) dal testo eccetto \t (0x09) e \n (0x0a), che sono whitespace legittimi. Applicato ai dati untrusted server-side (sender name, forward label, testo messaggio) prima del render terminale per prevenire ANSI/OSC injection. Non applicare agli URL: il sanitizer OSC 8 li gestisce separatamente.
func ToMessageMedia ¶
func ToMessageMedia(m tg.MessageMediaClass) *model.MessageMedia
ToMessageMedia converts a tg.MessageMediaClass to *model.MessageMedia. Returns nil for nil input, MessageMediaEmpty, MessageMediaWebPage, MessageMediaUnsupported, and other out-of-scope variants (Invoice, Game, Dice). Guarantees: non-nil output has Type != 0 (invariant from model package).
func Utf16Length ¶
Utf16Length conta UTF-16 code units in s. Necessario per segmentare il testo in renderTextWithLinks con corretto cursore.
func Utf16Slice ¶
Utf16Slice estrae text[offset:offset+length] usando UTF-16 code units. Telegram MTProto MessageEntity.Offset/Length sono UTF-16, non rune Go. Robusto a offset/length malformati: clamp ai bordi senza panic.
Types ¶
This section is empty.