package securechat import "encoding/json" // Event es el sobre estándar de los webhooks (docs/06-WEBHOOKS.md §2). `Data` depende de EventType. type Event struct { Version string `json:"version"` EventID string `json:"eventId"` EventType string `json:"eventType"` OccurredAt string `json:"occurredAt"` CompanyID string `json:"companyId"` ConversationID string `json:"conversationId"` ExternalUserRef string `json:"externalUserRef"` Metadata json.RawMessage `json:"metadata"` Data json.RawMessage `json:"data"` } // MessageCreated es `data` de message.created. type MessageCreated struct { MessageID string `json:"messageId"` SenderType string `json:"senderType"` SenderID string `json:"senderId"` ContentType string `json:"contentType"` Encryption Envelope `json:"encryption"` ConversationKey Wrap `json:"conversationKey"` Attachment *struct { AttachmentID string `json:"attachmentId"` Size int `json:"size"` } `json:"attachment"` } // ConversationStarted es `data` de conversation.started. type ConversationStarted struct { UserID string `json:"userId"` UserPublicKey string `json:"userPublicKey"` ConversationKey Wrap `json:"conversationKey"` InviteBinding *string `json:"inviteBinding"` IsReinvite bool `json:"isReinvite"` } // DecryptEvent descifra un message.created: abre data.conversationKey con tus llaves // [actual, anteriores…] y descifra data.encryption con senderType fijado en "user". // Devuelve el texto, K (para responder sin otro GET) y su keyVersion. func DecryptEvent(ev Event, companyKeys []KeyPair) (text string, key []byte, keyVersion int, err error) { var d MessageCreated if err := json.Unmarshal(ev.Data, &d); err != nil { return "", nil, 0, fail(ErrInvalidInput, "data de message.created inválido") } key, err = OpenWithAnyKey(d.ConversationKey, ev.ConversationID, companyKeys) if err != nil { return "", nil, 0, err } text, err = DecryptMessage(key, ev.ConversationID, "user", d.Encryption) if err != nil { return "", nil, 0, err } return text, key, d.ConversationKey.KeyVersion, nil }