whatsapp/pkg/connector/analytics.go
2024-09-27 14:44:15 +03:00

74 lines
2.6 KiB
Go

// mautrix-whatsapp - A Matrix-WhatsApp puppeting bridge.
// Copyright (C) 2024 Tulir Asokan
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package connector
import (
"crypto/hmac"
"crypto/sha256"
"encoding/binary"
"fmt"
"go.mau.fi/whatsmeow/proto/waE2E"
"go.mau.fi/whatsmeow/types"
"go.mau.fi/whatsmeow/types/events"
)
func (wa *WhatsAppClient) obfuscateJID(jid types.JID) string {
// Turn the first 4 bytes of HMAC-SHA256(user_mxid, phone) into a number and replace the middle of the actual phone with that deterministic random number.
randomNumber := binary.BigEndian.Uint32(hmac.New(sha256.New, []byte(wa.UserLogin.UserMXID)).Sum([]byte(jid.User))[:4])
return fmt.Sprintf("+%s-%d-%s:%d", jid.User[:1], randomNumber, jid.User[len(jid.User)-2:], jid.Device)
}
func (wa *WhatsAppClient) trackUndecryptable(evt *events.UndecryptableMessage) {
metricType := "error"
if evt.IsUnavailable {
metricType = "unavailable"
}
wa.UserLogin.TrackAnalytics("WhatsApp undecryptable message", map[string]any{
"messageID": evt.Info.ID,
"undecryptableType": metricType,
"decryptFailMode": evt.DecryptFailMode,
})
}
func (wa *WhatsAppClient) trackUndecryptableResolved(evt *events.Message) {
resolveType := "sender"
if evt.UnavailableRequestID != "" {
resolveType = "phone"
}
wa.UserLogin.TrackAnalytics("WhatsApp undecryptable message resolved", map[string]any{
"messageID": evt.Info.ID,
"resolveType": resolveType,
})
}
func (wa *WhatsAppClient) trackFoundRetry(receipt *events.Receipt, messageID types.MessageID, retryCount int, msg *waE2E.Message) bool {
wa.UserLogin.TrackAnalytics("WhatsApp incoming retry (accepted)", map[string]any{
"requester": wa.obfuscateJID(receipt.Sender),
"messageID": messageID,
"retryCount": retryCount,
})
return true
}
func (wa *WhatsAppClient) trackNotFoundRetry(requester, to types.JID, id types.MessageID) *waE2E.Message {
wa.UserLogin.TrackAnalytics("WhatsApp incoming retry (message not found)", map[string]any{
"requester": wa.obfuscateJID(requester),
"messageID": id,
})
return nil
}