Files
go-caatsm/internal/adapter/mapper/telegram.go
T

156 lines
3.9 KiB
Go
Raw Normal View History

package mapper
import (
"caatsm/internal/model"
"encoding/json"
"fmt"
"time"
"github.com/google/uuid"
)
// TelegramMapper maps between ParsedTelegram and database rows
type TelegramMapper struct{}
// NewTelegramMapper creates a new telegram mapper
func NewTelegramMapper() *TelegramMapper {
return &TelegramMapper{}
}
// ToDBRow converts a ParsedTelegram to a database row representation
func (m *TelegramMapper) ToDBRow(msg *model.ParsedTelegram) ([]interface{}, error) {
// Parse UUID
var msgUUID uuid.UUID
var err error
if msg.Uuid != "" {
msgUUID, err = uuid.Parse(msg.Uuid)
if err != nil {
return nil, fmt.Errorf("invalid UUID: %w", err)
}
} else {
msgUUID = uuid.New()
}
// Marshal BodyData to JSONB
var bodyDataJSON []byte
if msg.BodyData != nil {
bodyDataJSON, err = json.Marshal(msg.BodyData)
if err != nil {
return nil, fmt.Errorf("failed to marshal body data: %w", err)
}
}
// SecondaryAddresses is already a string, so we can use it directly
secondaryAddresses := msg.SecondaryAddresses
status := msg.Status
if status == "" {
status = model.MessageStatusUnknown
}
return []interface{}{
msgUUID, // uuid
msg.MessageID, // message_id
msg.DateTime, // date_time
msg.PriorityIndicator, // priority_indicator
msg.PrimaryAddress, // primary_address
secondaryAddresses, // secondary_addresses (TEXT)
msg.Originator, // originator
msg.OriginatorDateTime, // originator_date_time
msg.Category, // category
msg.Content, // content (TEXT, original message)
bodyDataJSON, // body_data (JSONB)
string(status), // status
msg.ErrorReason, // error_reason
msg.ReceivedAt, // received_at
msg.ParsedAt, // parsed_at
msg.DispatchedAt, // dispatched_at
msg.NeedDispatch, // need_dispatch
}, nil
}
// FromDBRow converts a database row to a ParsedTelegram
func (m *TelegramMapper) FromDBRow(row []interface{}) (*model.ParsedTelegram, error) {
const expectedColumns = 17
if len(row) < expectedColumns {
return nil, fmt.Errorf("expected %d columns, got %d", expectedColumns, len(row))
}
msgUUID, ok := row[0].(uuid.UUID)
if !ok {
return nil, fmt.Errorf("column 0 must be uuid.UUID")
}
toString := func(v interface{}) string {
if v == nil {
return ""
}
if s, ok := v.(string); ok {
return s
}
return fmt.Sprint(v)
}
parseTime := func(v interface{}) time.Time {
if v == nil {
return time.Time{}
}
if t, ok := v.(time.Time); ok {
return t
}
return time.Time{}
}
toBool := func(v interface{}) bool {
switch val := v.(type) {
case bool:
return val
case *bool:
return val != nil && *val
case int64:
return val != 0
default:
return false
}
}
var bodyData interface{}
if raw := row[10]; raw != nil {
switch val := raw.(type) {
case []byte:
if len(val) > 0 {
if err := json.Unmarshal(val, &bodyData); err != nil {
return nil, fmt.Errorf("failed to unmarshal body data: %w", err)
}
}
default:
bodyData = val
}
}
status := model.MessageStatusUnknown
if rawStatus := toString(row[11]); rawStatus != "" {
status = model.MessageStatus(rawStatus)
}
return &model.ParsedTelegram{
Uuid: msgUUID.String(),
MessageID: toString(row[1]),
DateTime: toString(row[2]),
PriorityIndicator: toString(row[3]),
PrimaryAddress: toString(row[4]),
SecondaryAddresses: toString(row[5]),
Originator: toString(row[6]),
OriginatorDateTime: toString(row[7]),
Category: toString(row[8]),
Content: toString(row[9]),
BodyData: bodyData,
Status: status,
ErrorReason: toString(row[12]),
ReceivedAt: parseTime(row[13]),
ParsedAt: parseTime(row[14]),
DispatchedAt: parseTime(row[15]),
NeedDispatch: toBool(row[16]),
}, nil
}