diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 146b93a0..73c8edda 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -30,8 +30,13 @@ jobs: run: | go install golang.org/x/tools/cmd/goimports@latest go install honnef.co/go/tools/cmd/staticcheck@latest - go install github.com/beeper/pre-commit-go/bridgelint@latest export PATH="$HOME/go/bin:$PATH" + - name: Cache pre-commit + uses: actions/cache@v6 + with: + path: ~/.cache/pre-commit + key: pre-commit-go${{ matrix.go-version }}-${{ hashFiles('.pre-commit-config.yaml') }} + - name: Run pre-commit - uses: pre-commit/action@v3.0.1 + run: pipx run pre-commit run --all-files --show-diff-on-failure --color=always diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1c96b066..d6c78bb4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -28,5 +28,4 @@ repos: - id: prevent-literal-http-methods - id: zerolog-ban-global-log - id: bridgelint - language: system verbose: true diff --git a/go.mod b/go.mod index f940c1de..6e9b5033 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( golang.org/x/sync v0.24.0 google.golang.org/protobuf v1.36.12 gopkg.in/yaml.v3 v3.0.1 - maunium.net/go/mautrix v0.32.1-0.20261105141340-842796acf445 + maunium.net/go/mautrix v0.32.1-0.20261031224934-b69deb427bd7 ) require ( diff --git a/go.sum b/go.sum index fb4e878f..12cf8f53 100644 --- a/go.sum +++ b/go.sum @@ -103,5 +103,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.32.1-0.20261105141340-842796acf445 h1:ZI9Y2YEmjqQDloOCiciHeynTRYjUwK0ZZbNcRH/5NOc= -maunium.net/go/mautrix v0.32.1-0.20261105141340-842796acf445/go.mod h1:tZSwPzw+/0pa0dxGufkh0uJqM84BNxB6e2I0+S0UyjU= +maunium.net/go/mautrix v0.32.1-0.20261031224934-b69deb427bd7 h1:GpLIqeJTpG0/ti7XA370HgjnSWd/pQxXVGb/FRkayOA= +maunium.net/go/mautrix v0.32.1-0.20261031224934-b69deb427bd7/go.mod h1:tZSwPzw+/0pa0dxGufkh0uJqM84BNxB6e2I0+S0UyjU= diff --git a/pkg/connector/backfill.go b/pkg/connector/backfill.go index 8f006e0b..cbc7eec8 100644 --- a/pkg/connector/backfill.go +++ b/pkg/connector/backfill.go @@ -298,9 +298,6 @@ func (wa *WhatsAppClient) handleWAHistorySync( Int("msg_index", i). Str("msg_id", rawMsg.GetMessage().GetKey().GetID()). Uint64("msg_time_seconds", rawMsg.GetMessage().GetMessageTimestamp()). - Stringer("stub_type", rawMsg.GetMessage().GetMessageStubType()). - Str("message_type", getMessageType(rawMsg.GetMessage().GetMessage())). - Bool("from_me", rawMsg.GetMessage().GetKey().GetFromMe()). Msg("Dropping historical message due to parse error") log.Trace(). Any("web_message_info", rawMsg.GetMessage()). diff --git a/pkg/connector/handlematrix.go b/pkg/connector/handlematrix.go index 84198506..d51efcd2 100644 --- a/pkg/connector/handlematrix.go +++ b/pkg/connector/handlematrix.go @@ -319,7 +319,7 @@ func (wa *WhatsAppClient) HandleMatrixMessageRemove(ctx context.Context, msg *br } func (wa *WhatsAppClient) HandleMatrixReadReceipt(ctx context.Context, receipt *bridgev2.MatrixReadReceipt) (retErr error) { - if receipt.Receipt.IsThread() || !receipt.ReadUpTo.After(receipt.LastRead) { + if !receipt.ReadUpTo.After(receipt.LastRead) { return nil } if receipt.LastRead.IsZero() { diff --git a/pkg/connector/handlewhatsapp.go b/pkg/connector/handlewhatsapp.go index e6174b92..4391233b 100644 --- a/pkg/connector/handlewhatsapp.go +++ b/pkg/connector/handlewhatsapp.go @@ -374,14 +374,6 @@ func (wa *WhatsAppClient) handleWAMessage(ctx context.Context, evt *events.Messa if assocType := messageAssoc.GetAssociationType(); assocType == waE2E.MessageAssociation_HD_IMAGE_DUAL_UPLOAD || assocType == waE2E.MessageAssociation_HD_VIDEO_DUAL_UPLOAD { parentKey := messageAssoc.GetParentMessageKey() protocolMsg, shouldHideEdit := makeHDMediaReplacementEdit(evt.Message, parentKey) - if protocolMsg.GetEditedMessage() == nil { - wa.UserLogin.Log.Debug(). - Str("message_id", evt.Info.ID). - Str("parent_id", parentKey.GetID()). - Stringer("assoc_type", assocType). - Msg("Ignoring HD replacement message without replacement content") - return - } dontRenderEdited = shouldHideEdit wa.UserLogin.Log.Debug(). Str("message_id", evt.Info.ID). diff --git a/pkg/connector/lidmigrate.go b/pkg/connector/lidmigrate.go index 4295be63..17b24287 100644 --- a/pkg/connector/lidmigrate.go +++ b/pkg/connector/lidmigrate.go @@ -300,11 +300,7 @@ func (wa *WhatsAppConnector) syncMismatchingGhosts(ctx context.Context) error { } func (wa *WhatsAppConnector) removeRejoinedPNGhosts(ctx context.Context) error { - if wa.Bridge.Background || wa.Bridge.DB.KV.Get(ctx, "whatsapp_lid_dm_pn_ghosts_removed_v2") == "true" { - return nil - } - stateGetter, ok := wa.Bridge.Matrix.(bridgev2.MatrixConnectorWithArbitraryRoomState) - if !ok { + if wa.Bridge.Background || wa.Bridge.DB.KV.Get(ctx, "whatsapp_lid_dm_pn_ghosts_removed") == "true" { return nil } log := zerolog.Ctx(ctx).With().Str("action", "remove rejoined pn ghosts").Logger() @@ -326,14 +322,12 @@ func (wa *WhatsAppConnector) removeRejoinedPNGhosts(ctx context.Context) error { continue } pnUserID := waid.MakeUserID(pn) - memberEvt, err := stateGetter.GetStateEvent(ctx, portal.MXID, event.StateMember, wa.Bridge.Matrix.FormatGhostMXID(pnUserID).String()) - if errors.Is(err, mautrix.MNotFound) || errors.Is(err, mautrix.MForbidden) { - continue - } else if err != nil { + member, err := wa.Bridge.Matrix.GetMemberInfo(ctx, portal.MXID, wa.Bridge.Matrix.FormatGhostMXID(pnUserID)) + if err != nil { log.Warn().Err(err).Stringer("room_id", portal.MXID).Msg("Failed to get PN ghost membership") failed++ continue - } else if memberEvt == nil || memberEvt.Content.AsMember().Membership != event.MembershipJoin { + } else if member == nil || member.Membership != event.MembershipJoin { continue } pnGhost, err := wa.Bridge.GetGhostByID(ctx, pnUserID) @@ -351,12 +345,6 @@ func (wa *WhatsAppConnector) removeRejoinedPNGhosts(ctx context.Context) error { } continue } - log.Debug(). - Stringer("room_id", portal.MXID). - Stringer("pn", pn). - Stringer("join_sender", memberEvt.Sender). - Time("join_ts", time.UnixMilli(memberEvt.Timestamp)). - Msg("Removed PN ghost from LID DM") removed++ } log.Info(). @@ -365,7 +353,7 @@ func (wa *WhatsAppConnector) removeRejoinedPNGhosts(ctx context.Context) error { Int("total_lid_portals", len(lidPortals)). Msg("Finished removing rejoined PN ghosts from LID DMs") if failed == 0 && ctx.Err() == nil { - wa.Bridge.DB.KV.Set(ctx, "whatsapp_lid_dm_pn_ghosts_removed_v2", "true") + wa.Bridge.DB.KV.Set(ctx, "whatsapp_lid_dm_pn_ghosts_removed", "true") } return nil } diff --git a/pkg/connector/muse.go b/pkg/connector/muse.go index 4a589ce7..ee6b04d9 100644 --- a/pkg/connector/muse.go +++ b/pkg/connector/muse.go @@ -4,6 +4,7 @@ import ( "context" "encoding/base64" "encoding/json" + "errors" "fmt" "runtime/debug" "time" @@ -56,9 +57,9 @@ func (wa *WhatsAppClient) resyncWASARootSecrets(ctx context.Context) { success := true if err := wa.Client.FetchAppState(ctx, appstate.WAPatchRegularHigh, true, false); err != nil { log.Err(err).Msg("Failed to resync WASA root secrets") - // Mark the sync as completed on errors too, because some get permanently stuck (mismatching LTHash, - // expired patch blobs), and a failed full sync already requests app state recovery from the phone. - if ctx.Err() != nil { + // Mark the sync as completed on mismatching LTHash errors, because those can get permanently stuck + // (retrying won't help). In case it's not stuck, a single call should be enough to request a resync. + if !errors.Is(err, appstate.ErrMismatchingLTHash) || ctx.Err() != nil { return } success = false diff --git a/pkg/connector/userinfo.go b/pkg/connector/userinfo.go index 387971e9..b6594534 100644 --- a/pkg/connector/userinfo.go +++ b/pkg/connector/userinfo.go @@ -119,7 +119,6 @@ func (wa *WhatsAppClient) doGhostResync(ctx context.Context, queue map[types.JID var ghostJIDs []types.JID var ghosts []*bridgev2.Ghost var portals []*bridgev2.Portal - selectedGhosts := make(map[types.JID]*bridgev2.Ghost) for jid, item := range queue { var lastSync time.Time unknownAvatar := false @@ -137,23 +136,12 @@ func (wa *WhatsAppClient) doGhostResync(ctx context.Context, queue map[types.JID continue } if item.ghost != nil { - selectedGhosts[jid] = item.ghost + ghosts = append(ghosts, item.ghost) + ghostJIDs = append(ghostJIDs, jid) } else if item.portal != nil { portals = append(portals, item.portal) } } - for jid, ghost := range selectedGhosts { - if jid.Server == types.DefaultUserServer { - lid, err := wa.GetStore().LIDs.GetLIDForPN(ctx, jid) - if err != nil { - log.Warn().Err(err).Stringer("jid", jid).Msg("Failed to get LID for background sync") - } else if _, lidSelected := selectedGhosts[lid]; lidSelected { - continue - } - } - ghosts = append(ghosts, ghost) - ghostJIDs = append(ghostJIDs, jid) - } for _, portal := range portals { wa.UserLogin.QueueRemoteEvent(&simplevent.ChatResync{ EventMeta: simplevent.EventMeta{ diff --git a/pkg/msgconv/wa-rich-response.go b/pkg/msgconv/wa-rich-response.go index e506a64e..28a648c3 100644 --- a/pkg/msgconv/wa-rich-response.go +++ b/pkg/msgconv/wa-rich-response.go @@ -29,7 +29,6 @@ import ( "github.com/yuin/goldmark/extension" "go.mau.fi/whatsmeow/types/richresponse" "maunium.net/go/mautrix/bridgev2" - "maunium.net/go/mautrix/crypto/canonicaljson" "maunium.net/go/mautrix/event" "maunium.net/go/mautrix/format" "maunium.net/go/mautrix/format/mdext" @@ -37,8 +36,7 @@ import ( func (mc *MessageConverter) convertUnifiedRichResponseMessage(ctx context.Context, data []byte) *bridgev2.ConvertedMessagePart { extra := map[string]any{} - _, canonicalErr := canonicaljson.Marshal(json.RawMessage(data)) - if canonicalErr == nil && len(data) < 24*1024 { + if json.Valid(data) && len(data) < 24*1024 { extra["fi.mau.whatsapp.rich_message"] = json.RawMessage(data) } else if len(data) < 16*1024 { extra["fi.mau.whatsapp.non_json_rich_message"] = base64.StdEncoding.EncodeToString(data)