mirror of
https://github.com/mautrix/whatsapp.git
synced 2025-03-14 14:15:38 +00:00
analytics: track undecryptable messages
This commit is contained in:
parent
512f450847
commit
5deafa0112
6 changed files with 129 additions and 3 deletions
2
go.mod
2
go.mod
|
@ -22,7 +22,7 @@ require (
|
|||
golang.org/x/sync v0.8.0
|
||||
google.golang.org/protobuf v1.34.2
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
maunium.net/go/mautrix v0.21.1-0.20240926091654-7a5f15b03c2e
|
||||
maunium.net/go/mautrix v0.21.1-0.20240927113633-d1e5b09d972b
|
||||
)
|
||||
|
||||
require (
|
||||
|
|
4
go.sum
4
go.sum
|
@ -114,5 +114,5 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
|||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
maunium.net/go/mauflag v1.0.0 h1:YiaRc0tEI3toYtJMRIfjP+jklH45uDHtT80nUamyD4M=
|
||||
maunium.net/go/mauflag v1.0.0/go.mod h1:nLivPOpTpHnpzEh8jEdSL9UqO9+/KBJFmNRlwKfkPeA=
|
||||
maunium.net/go/mautrix v0.21.1-0.20240926091654-7a5f15b03c2e h1:elQExbBoPGaI0jKMt2IzhpGT7NoTUqZCFxNSvRw0s1A=
|
||||
maunium.net/go/mautrix v0.21.1-0.20240926091654-7a5f15b03c2e/go.mod h1:qm9oDhcHxF/Xby5RUuONIGpXw1SXXqLZj/GgvMxJxu0=
|
||||
maunium.net/go/mautrix v0.21.1-0.20240927113633-d1e5b09d972b h1:YeiQzkT0HXTqcH7BgbsNiD5CbUpEf80pf/wUpCTQ3j4=
|
||||
maunium.net/go/mautrix v0.21.1-0.20240927113633-d1e5b09d972b/go.mod h1:qm9oDhcHxF/Xby5RUuONIGpXw1SXXqLZj/GgvMxJxu0=
|
||||
|
|
74
pkg/connector/analytics.go
Normal file
74
pkg/connector/analytics.go
Normal file
|
@ -0,0 +1,74 @@
|
|||
// 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
|
||||
}
|
|
@ -1,3 +1,19 @@
|
|||
// 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 (
|
||||
|
@ -47,6 +63,8 @@ func (wa *WhatsAppConnector) LoadUserLogin(_ context.Context, login *bridgev2.Us
|
|||
w.Client = whatsmeow.NewClient(w.Device, waLog.Zerolog(log))
|
||||
w.Client.AddEventHandler(w.handleWAEvent)
|
||||
w.Client.AutomaticMessageRerequestFromPhone = true
|
||||
w.Client.GetMessageForRetry = w.trackNotFoundRetry
|
||||
w.Client.PreRetryCallback = w.trackFoundRetry
|
||||
w.Client.SetForceActiveDeliveryReceipts(wa.Config.ForceActiveDeliveryReceipts)
|
||||
} else {
|
||||
w.UserLogin.Log.Warn().Stringer("jid", w.JID).Msg("No device found for user in whatsmeow store")
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
// 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 (
|
||||
|
@ -169,6 +185,7 @@ func (evt *WAMessageEvent) GetType() bridgev2.RemoteEventType {
|
|||
|
||||
func (evt *WAMessageEvent) HandleExisting(ctx context.Context, portal *bridgev2.Portal, intent bridgev2.MatrixAPI, existing []*database.Message) (bridgev2.UpsertResult, error) {
|
||||
if existing[0].Metadata.(*waid.MessageMetadata).Error == waid.MsgErrDecryptionFailed {
|
||||
evt.wa.trackUndecryptableResolved(evt.MsgEvent)
|
||||
zerolog.Ctx(ctx).Debug().
|
||||
Stringer("existing_mxid", existing[0].MXID).
|
||||
Msg("Received decryptable version of previously undecryptable message")
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
// 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 (
|
||||
|
@ -242,6 +258,7 @@ func (wa *WhatsAppClient) handleWAUndecryptableMessage(evt *events.Undecryptable
|
|||
Bool("unavailable", evt.IsUnavailable).
|
||||
Str("decrypt_fail", string(evt.DecryptFailMode)).
|
||||
Msg("Received undecryptable WhatsApp message")
|
||||
wa.trackUndecryptable(evt)
|
||||
if evt.DecryptFailMode == events.DecryptFailHide || evt.Info.Chat.Server == types.HiddenUserServer || evt.Info.Sender.Server == types.HiddenUserServer {
|
||||
return
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue