Ctrl K
ComunidadGuías…

internal/store/postgres/media_codec.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package postgres

import (
	"encoding/json"
	"fmt"
	"reflect"

	"telesrv/internal/domain"
)

// Media-related JSON encoding/decoding: domain value objects ↔ JSONB columns. domain.* carries json tags and can be marshaled directly.

// jsonArrayOrEmpty serializes a slice to JSONB; nil serializes to "[]" (the column is NOT NULL DEFAULT '[]').
func jsonArrayOrEmpty(v any) ([]byte, error) {
	b, err := json.Marshal(v)
	if err != nil {
		return nil, err
	}
	if string(b) == "null" {
		return []byte("[]"), nil
	}
	return b, nil
}

// encodeMessageMedia serializes a message media snapshot to JSONB; no media serializes to "{}".
func encodeMessageMedia(m *domain.MessageMedia) ([]byte, error) {
	if m.IsZero() {
		return []byte("{}"), nil
	}
	return json.Marshal(m)
}

// decodeMessageMedia restores the media JSONB text of a message row to *MessageMedia; an empty payload returns nil.
func decodeMessageMedia(s string) (*domain.MessageMedia, error) {
	if s == "" || s == "{}" || s == "null" {
		return nil, nil
	}
	var m domain.MessageMedia
	if err := json.Unmarshal([]byte(s), &m); err != nil {
		return nil, err
	}
	if m.IsZero() {
		return nil, nil
	}
	return &m, nil
}

// encodeReplyMarkup serializes a reply/inline keyboard snapshot to JSONB; an empty markup serializes to "{}".
// callback data is []byte and json.Marshal base64-encodes it automatically (guaranteeing a byte-level round-trip through JSONB).
func encodeReplyMarkup(m *domain.MessageReplyMarkup) ([]byte, error) {
	if err := domain.ValidateReplyMarkup(m); err != nil {
		return nil, fmt.Errorf("encode reply markup: %w", err)
	}
	if m.IsZero() {
		return []byte("{}"), nil
	}
	return json.Marshal(m)
}

// decodeReplyMarkup restores the reply_markup JSONB text of a message row to
// *MessageReplyMarkup; an empty payload returns nil.
func decodeReplyMarkup(s string) (*domain.MessageReplyMarkup, error) {
	if s == "" || s == "{}" || s == "null" {
		return nil, nil
	}
	var m domain.MessageReplyMarkup
	if err := json.Unmarshal([]byte(s), &m); err != nil {
		return nil, err
	}
	if err := domain.ValidateReplyMarkup(&m); err != nil {
		return nil, fmt.Errorf("decode reply markup: %w", err)
	}
	if m.IsZero() {
		return nil, nil
	}
	return &m, nil
}

// encodeRichMessage serializes a rich text message snapshot to JSONB; an empty payload serializes to "{}".
// Blocks is []byte (opaque TL) and json.Marshal base64-encodes it automatically, guaranteeing a byte-level round-trip through JSONB.
func encodeRichMessage(m *domain.MessageRichMessage) ([]byte, error) {
	if m.IsZero() {
		return []byte("{}"), nil
	}
	return json.Marshal(m)
}

// decodeRichMessage restores the rich_message JSONB text of a message row to
// *MessageRichMessage; an empty payload returns nil.
func decodeRichMessage(s string) (*domain.MessageRichMessage, error) {
	if s == "" || s == "{}" || s == "null" {
		return nil, nil
	}
	var m domain.MessageRichMessage
	if err := json.Unmarshal([]byte(s), &m); err != nil {
		return nil, err
	}
	if m.IsZero() {
		return nil, nil
	}
	return &m, nil
}

func richMessagesEqual(a, b *domain.MessageRichMessage) bool {
	if a.IsZero() && b.IsZero() {
		return true
	}
	return reflect.DeepEqual(a, b)
}

func decodePhotoSizes(s string) ([]domain.PhotoSize, error) {
	if s == "" || s == "[]" || s == "null" {
		return nil, nil
	}
	var out []domain.PhotoSize
	if err := json.Unmarshal([]byte(s), &out); err != nil {
		return nil, err
	}
	return out, nil
}

func decodeDocumentAttributes(s string) ([]domain.DocumentAttribute, error) {
	if s == "" || s == "[]" || s == "null" {
		return nil, nil
	}
	var out []domain.DocumentAttribute
	if err := json.Unmarshal([]byte(s), &out); err != nil {
		return nil, err
	}
	return out, nil
}

func decodeInt64Slice(s string) ([]int64, error) {
	if s == "" || s == "[]" || s == "null" {
		return nil, nil
	}
	var out []int64
	if err := json.Unmarshal([]byte(s), &out); err != nil {
		return nil, err
	}
	return out, nil
}

func decodeStickerPacks(s string) ([]domain.StickerPack, error) {
	if s == "" || s == "[]" || s == "null" {
		return nil, nil
	}
	var out []domain.StickerPack
	if err := json.Unmarshal([]byte(s), &out); err != nil {
		return nil, err
	}
	return out, nil
}

func decodeStickerKeywords(s string) ([]domain.StickerKeyword, error) {
	if s == "" || s == "[]" || s == "null" {
		return nil, nil
	}
	var out []domain.StickerKeyword
	if err := json.Unmarshal([]byte(s), &out); err != nil {
		return nil, err
	}
	return out, nil
}