From fd0dc5c78d8056ae2047deaf57c70bc66a28871c Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Wed, 26 Jun 2024 15:36:06 +0300 Subject: [PATCH] Update whatsmeow --- cmd/lscli/go.mod | 2 +- cmd/lscli/go.sum | 4 +-- go.mod | 2 +- go.sum | 4 +-- messagix/e2ee-register.go | 11 ++++--- msgconv/from-whatsapp.go | 20 ++++++------- msgconv/to-whatsapp.go | 60 +++++++++++++++++++-------------------- portal.go | 37 +++++++++++++----------- 8 files changed, 72 insertions(+), 68 deletions(-) diff --git a/cmd/lscli/go.mod b/cmd/lscli/go.mod index 52b695f..96a797e 100644 --- a/cmd/lscli/go.mod +++ b/cmd/lscli/go.mod @@ -22,7 +22,7 @@ require ( github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.0 // indirect go.mau.fi/libsignal v0.1.0 // indirect - go.mau.fi/whatsmeow v0.0.0-20240507080416-01b0547014dc // indirect + go.mau.fi/whatsmeow v0.0.0-20240625083845-6acab596dd8c // indirect golang.org/x/crypto v0.24.0 // indirect golang.org/x/net v0.26.0 // indirect golang.org/x/sys v0.21.0 // indirect diff --git a/cmd/lscli/go.sum b/cmd/lscli/go.sum index ed169e5..a4a7b42 100644 --- a/cmd/lscli/go.sum +++ b/cmd/lscli/go.sum @@ -38,8 +38,8 @@ go.mau.fi/libsignal v0.1.0 h1:vAKI/nJ5tMhdzke4cTK1fb0idJzz1JuEIpmjprueC+c= go.mau.fi/libsignal v0.1.0/go.mod h1:R8ovrTezxtUNzCQE5PH30StOQWWeBskBsWE55vMfY9I= go.mau.fi/util v0.5.1-0.20240625181823-38eefa626984 h1:63X00R1qL5G+m2LWxdKzAS8cyihFu5IaaOzJ7QHvkzs= go.mau.fi/util v0.5.1-0.20240625181823-38eefa626984/go.mod h1:DsJzUrJAG53lCZnnYvq9/mOyLuPScWwYhvETiTrpdP4= -go.mau.fi/whatsmeow v0.0.0-20240507080416-01b0547014dc h1:lcx1lVelwGYnRAFNlYmz2T6mjghUYV4zhFbUOX4D1tQ= -go.mau.fi/whatsmeow v0.0.0-20240507080416-01b0547014dc/go.mod h1:kNI5foyzqd77d5HaWc1Jico6/rxtZ/UE8nr80hIsbIk= +go.mau.fi/whatsmeow v0.0.0-20240625083845-6acab596dd8c h1:yiULssyKHJcFA1fae2NJkwU7QW4EHQs7QEWoIqfqilA= +go.mau.fi/whatsmeow v0.0.0-20240625083845-6acab596dd8c/go.mod h1:0+65CYaE6r4dWzr0dN8i+UZKy0gIfJ79VuSqIl0nKRM= golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= diff --git a/go.mod b/go.mod index 98a56f9..22f06dc 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/tidwall/gjson v1.17.1 go.mau.fi/libsignal v0.1.0 go.mau.fi/util v0.5.1-0.20240625181823-38eefa626984 - go.mau.fi/whatsmeow v0.0.0-20240507080416-01b0547014dc + go.mau.fi/whatsmeow v0.0.0-20240625083845-6acab596dd8c golang.org/x/crypto v0.24.0 golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 golang.org/x/image v0.18.0 diff --git a/go.sum b/go.sum index 5136a57..1093313 100644 --- a/go.sum +++ b/go.sum @@ -51,8 +51,8 @@ go.mau.fi/libsignal v0.1.0 h1:vAKI/nJ5tMhdzke4cTK1fb0idJzz1JuEIpmjprueC+c= go.mau.fi/libsignal v0.1.0/go.mod h1:R8ovrTezxtUNzCQE5PH30StOQWWeBskBsWE55vMfY9I= go.mau.fi/util v0.5.1-0.20240625181823-38eefa626984 h1:63X00R1qL5G+m2LWxdKzAS8cyihFu5IaaOzJ7QHvkzs= go.mau.fi/util v0.5.1-0.20240625181823-38eefa626984/go.mod h1:DsJzUrJAG53lCZnnYvq9/mOyLuPScWwYhvETiTrpdP4= -go.mau.fi/whatsmeow v0.0.0-20240507080416-01b0547014dc h1:lcx1lVelwGYnRAFNlYmz2T6mjghUYV4zhFbUOX4D1tQ= -go.mau.fi/whatsmeow v0.0.0-20240507080416-01b0547014dc/go.mod h1:kNI5foyzqd77d5HaWc1Jico6/rxtZ/UE8nr80hIsbIk= +go.mau.fi/whatsmeow v0.0.0-20240625083845-6acab596dd8c h1:yiULssyKHJcFA1fae2NJkwU7QW4EHQs7QEWoIqfqilA= +go.mau.fi/whatsmeow v0.0.0-20240625083845-6acab596dd8c/go.mod h1:0+65CYaE6r4dWzr0dN8i+UZKy0gIfJ79VuSqIl0nKRM= go.mau.fi/zeroconfig v0.1.2 h1:DKOydWnhPMn65GbXZOafgkPm11BvFashZWLct0dGFto= go.mau.fi/zeroconfig v0.1.2/go.mod h1:NcSJkf180JT+1IId76PcMuLTNa1CzsFFZ0nBygIQM70= golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= diff --git a/messagix/e2ee-register.go b/messagix/e2ee-register.go index 51fea85..03cdfe0 100644 --- a/messagix/e2ee-register.go +++ b/messagix/e2ee-register.go @@ -35,12 +35,11 @@ import ( "github.com/google/uuid" "github.com/rs/zerolog" "go.mau.fi/libsignal/ecc" - "google.golang.org/protobuf/proto" - - "go.mau.fi/whatsmeow/binary/armadillo/waArmadilloICDC" waProto "go.mau.fi/whatsmeow/binary/proto" + "go.mau.fi/whatsmeow/proto/waArmadilloICDC" "go.mau.fi/whatsmeow/store" "go.mau.fi/whatsmeow/types" + "google.golang.org/protobuf/proto" ) type ICDCFetchResponse struct { @@ -168,10 +167,10 @@ func (c *Client) RegisterE2EE(ctx context.Context, fbid int64) error { } icdcTS := time.Now().Unix() unsignedList, err := proto.Marshal(&waArmadilloICDC.ICDCIdentityList{ - Seq: int32(icdcMeta.ICDCSeq), - Timestamp: icdcTS, + Seq: proto.Int32(int32(icdcMeta.ICDCSeq)), + Timestamp: proto.Int64(icdcTS), Devices: sliceifyIdentities(deviceIdentities), - SigningDeviceIndex: int32(ownIdentityIndex), + SigningDeviceIndex: proto.Int32(int32(ownIdentityIndex)), }) if err != nil { return fmt.Errorf("failed to marshal ICDC identity list: %w", err) diff --git a/msgconv/from-whatsapp.go b/msgconv/from-whatsapp.go index 22230dd..7c2505e 100644 --- a/msgconv/from-whatsapp.go +++ b/msgconv/from-whatsapp.go @@ -29,11 +29,11 @@ import ( "go.mau.fi/util/exmime" "go.mau.fi/util/ffmpeg" "go.mau.fi/whatsmeow" - "go.mau.fi/whatsmeow/binary/armadillo/waArmadilloApplication" - "go.mau.fi/whatsmeow/binary/armadillo/waArmadilloXMA" - "go.mau.fi/whatsmeow/binary/armadillo/waCommon" - "go.mau.fi/whatsmeow/binary/armadillo/waConsumerApplication" - "go.mau.fi/whatsmeow/binary/armadillo/waMediaTransport" + "go.mau.fi/whatsmeow/proto/waArmadilloApplication" + "go.mau.fi/whatsmeow/proto/waArmadilloXMA" + "go.mau.fi/whatsmeow/proto/waCommon" + "go.mau.fi/whatsmeow/proto/waConsumerApplication" + "go.mau.fi/whatsmeow/proto/waMediaTransport" "go.mau.fi/whatsmeow/types" "go.mau.fi/whatsmeow/types/events" _ "golang.org/x/image/webp" @@ -52,7 +52,7 @@ func (mc *MessageConverter) WhatsAppTextToMatrix(ctx context.Context, text *waCo silent := false if len(text.Commands) > 0 { for _, cmd := range text.Commands { - switch cmd.CommandType { + switch cmd.GetCommandType() { case waCommon.Command_SILENT: silent = true content.Mentions.Room = false @@ -370,13 +370,13 @@ func (mc *MessageConverter) waConsumerToMatrix(ctx context.Context, rawContent * } func (mc *MessageConverter) waExtendedContentMessageToMatrix(ctx context.Context, content *waArmadilloXMA.ExtendedContentMessage) (parts []*ConvertedMessagePart) { - body := content.MessageText + body := content.GetMessageText() for _, cta := range content.GetCtas() { - if strings.HasPrefix(cta.NativeURL, "https://") && !strings.Contains(body, cta.NativeURL) { + if strings.HasPrefix(cta.GetNativeURL(), "https://") && !strings.Contains(body, cta.GetNativeURL()) { if body == "" { - body = cta.NativeURL + body = cta.GetNativeURL() } else { - body = fmt.Sprintf("%s\n\n%s", body, cta.NativeURL) + body = fmt.Sprintf("%s\n\n%s", body, cta.GetNativeURL()) } } } diff --git a/msgconv/to-whatsapp.go b/msgconv/to-whatsapp.go index d84d930..85aaae1 100644 --- a/msgconv/to-whatsapp.go +++ b/msgconv/to-whatsapp.go @@ -27,19 +27,19 @@ import ( "go.mau.fi/util/ffmpeg" "go.mau.fi/whatsmeow" - "go.mau.fi/whatsmeow/binary/armadillo/waMediaTransport" - "go.mau.fi/whatsmeow/binary/armadillo/waMsgApplication" + "go.mau.fi/whatsmeow/proto/waCommon" + "go.mau.fi/whatsmeow/proto/waConsumerApplication" + "go.mau.fi/whatsmeow/proto/waMediaTransport" + "go.mau.fi/whatsmeow/proto/waMsgApplication" "go.mau.fi/whatsmeow/types" + "google.golang.org/protobuf/proto" "maunium.net/go/mautrix/event" - - "go.mau.fi/whatsmeow/binary/armadillo/waCommon" - "go.mau.fi/whatsmeow/binary/armadillo/waConsumerApplication" ) func (mc *MessageConverter) TextToWhatsApp(content *event.MessageEventContent) *waCommon.MessageText { // TODO mentions return &waCommon.MessageText{ - Text: content.Body, + Text: proto.String(content.Body), } } @@ -88,11 +88,11 @@ func (mc *MessageConverter) ToWhatsApp( waContent.Content = &waConsumerApplication.ConsumerApplication_Content_LocationMessage{ LocationMessage: &waConsumerApplication.ConsumerApplication_LocationMessage{ Location: &waConsumerApplication.ConsumerApplication_Location{ - DegreesLatitude: lat, - DegreesLongitude: long, - Name: content.Body, + DegreesLatitude: proto.Float64(lat), + DegreesLongitude: proto.Float64(long), + Name: proto.String(content.Body), }, - Address: "Earth", + Address: proto.String("Earth"), }, } default: @@ -101,10 +101,10 @@ func (mc *MessageConverter) ToWhatsApp( var meta waMsgApplication.MessageApplication_Metadata if replyTo := mc.GetMetaReply(ctx, content); replyTo != nil { meta.QuotedMessage = &waMsgApplication.MessageApplication_Metadata_QuotedMessage{ - StanzaID: replyTo.ReplyMessageId, + StanzaID: proto.String(replyTo.ReplyMessageId), // TODO: this is hacky since it hardcodes the server // TODO 2: should this be included for DMs? - Participant: types.JID{User: strconv.FormatInt(replyTo.ReplySender, 10), Server: types.MessengerServer}.String(), + Participant: proto.String(types.JID{User: strconv.FormatInt(replyTo.ReplySender, 10), Server: types.MessengerServer}.String()), Payload: nil, } } @@ -197,20 +197,20 @@ func (mc *MessageConverter) reuploadMediaToWhatsApp(ctx context.Context, evt *ev FileSHA256: uploaded.FileSHA256, MediaKey: uploaded.MediaKey, FileEncSHA256: uploaded.FileEncSHA256, - DirectPath: uploaded.DirectPath, - MediaKeyTimestamp: time.Now().Unix(), + DirectPath: &uploaded.DirectPath, + MediaKeyTimestamp: proto.Int64(time.Now().Unix()), }, Ancillary: &waMediaTransport.WAMediaTransport_Ancillary{ - FileLength: uint64(len(data)), - Mimetype: mimeType, + FileLength: proto.Uint64(uint64(len(data))), + Mimetype: &mimeType, // This field is extremely required for some reason. // Messenger iOS & Android will refuse to display the media if it's not present. // iOS also requires that width and height are non-empty. Thumbnail: &waMediaTransport.WAMediaTransport_Ancillary_Thumbnail{ - ThumbnailWidth: uint32(w), - ThumbnailHeight: uint32(h), + ThumbnailWidth: proto.Uint32(uint32(w)), + ThumbnailHeight: proto.Uint32(uint32(h)), }, - ObjectID: uploaded.ObjectID, + ObjectID: &uploaded.ObjectID, }, } fmt.Printf("Uploaded media transport: %+v\n", mediaTransport) @@ -234,8 +234,8 @@ func (mc *MessageConverter) wrapWhatsAppMedia( Transport: reuploaded, }, Ancillary: &waMediaTransport.ImageTransport_Ancillary{ - Height: uint32(content.Info.Height), - Width: uint32(content.Info.Width), + Height: proto.Uint32(uint32(content.Info.Height)), + Width: proto.Uint32(uint32(content.Info.Width)), }, }) output = &waConsumerApplication.ConsumerApplication_Content_ImageMessage{ImageMessage: imageMsg} @@ -246,8 +246,8 @@ func (mc *MessageConverter) wrapWhatsAppMedia( Transport: reuploaded, }, Ancillary: &waMediaTransport.StickerTransport_Ancillary{ - Height: uint32(content.Info.Height), - Width: uint32(content.Info.Width), + Height: proto.Uint32(uint32(content.Info.Height)), + Width: proto.Uint32(uint32(content.Info.Width)), }, }) output = &waConsumerApplication.ConsumerApplication_Content_StickerMessage{StickerMessage: stickerMsg} @@ -263,30 +263,30 @@ func (mc *MessageConverter) wrapWhatsAppMedia( Transport: reuploaded, }, Ancillary: &waMediaTransport.VideoTransport_Ancillary{ - Height: uint32(content.Info.Height), - Width: uint32(content.Info.Width), - Seconds: uint32(content.Info.Duration / 1000), - GifPlayback: isGif, + Height: proto.Uint32(uint32(content.Info.Height)), + Width: proto.Uint32(uint32(content.Info.Width)), + Seconds: proto.Uint32(uint32(content.Info.Duration / 1000)), + GifPlayback: &isGif, }, }) output = &waConsumerApplication.ConsumerApplication_Content_VideoMessage{VideoMessage: videoMsg} case event.MsgAudio: _, isVoice := evt.Content.Raw["org.matrix.msc3245.voice"] audioMsg := &waConsumerApplication.ConsumerApplication_AudioMessage{ - PTT: isVoice, + PTT: &isVoice, } err = audioMsg.Set(&waMediaTransport.AudioTransport{ Integral: &waMediaTransport.AudioTransport_Integral{ Transport: reuploaded, }, Ancillary: &waMediaTransport.AudioTransport_Ancillary{ - Seconds: uint32(content.Info.Duration / 1000), + Seconds: proto.Uint32(uint32(content.Info.Duration / 1000)), }, }) output = &waConsumerApplication.ConsumerApplication_Content_AudioMessage{AudioMessage: audioMsg} case event.MsgFile: documentMsg := &waConsumerApplication.ConsumerApplication_DocumentMessage{ - FileName: fileName, + FileName: &fileName, } err = documentMsg.Set(&waMediaTransport.DocumentTransport{ Integral: &waMediaTransport.DocumentTransport_Integral{ diff --git a/portal.go b/portal.go index 0e01749..ca59c5c 100644 --- a/portal.go +++ b/portal.go @@ -31,12 +31,13 @@ import ( "go.mau.fi/util/exzerolog" "go.mau.fi/util/variationselector" "go.mau.fi/whatsmeow" - "go.mau.fi/whatsmeow/binary/armadillo/waArmadilloApplication" - "go.mau.fi/whatsmeow/binary/armadillo/waCommon" - "go.mau.fi/whatsmeow/binary/armadillo/waConsumerApplication" - "go.mau.fi/whatsmeow/binary/armadillo/waMsgApplication" + "go.mau.fi/whatsmeow/proto/waArmadilloApplication" + "go.mau.fi/whatsmeow/proto/waCommon" + "go.mau.fi/whatsmeow/proto/waConsumerApplication" + "go.mau.fi/whatsmeow/proto/waMsgApplication" "go.mau.fi/whatsmeow/types" "go.mau.fi/whatsmeow/types/events" + "google.golang.org/protobuf/proto" "maunium.net/go/mautrix" "maunium.net/go/mautrix/appservice" "maunium.net/go/mautrix/bridge" @@ -759,7 +760,7 @@ func (portal *Portal) handleMatrixEdit(ctx context.Context, sender *User, isRela consumerMsg := wrapEdit(&waConsumerApplication.ConsumerApplication_EditMessage{ Key: portal.buildMessageKey(sender, editTargetMsg), Message: portal.MsgConv.TextToWhatsApp(content), - TimestampMS: evt.Timestamp, + TimestampMS: &evt.Timestamp, }) var resp whatsmeow.SendResponse resp, err = sender.E2EEClient.SendFBMessage(ctx, portal.JID(), consumerMsg, nil) @@ -946,15 +947,19 @@ func wrapReaction(message *waConsumerApplication.ConsumerApplication_ReactionMes } func (portal *Portal) buildMessageKey(user *User, targetMsg *database.Message) *waCommon.MessageKey { - var messageKeyParticipant string + var messageKeyParticipant *string if !portal.IsPrivateChat() { // TODO: this is hacky since it hardcodes the server - messageKeyParticipant = types.JID{User: strconv.FormatInt(targetMsg.Sender, 10), Server: types.MessengerServer}.String() + messageKeyParticipant = proto.String(types.JID{User: strconv.FormatInt(targetMsg.Sender, 10), Server: types.MessengerServer}.String()) + } + var fromMe *bool + if targetMsg.Sender == user.MetaID { + fromMe = proto.Bool(true) } return &waCommon.MessageKey{ - RemoteJID: portal.JID().String(), - FromMe: targetMsg.Sender == user.MetaID, - ID: targetMsg.ID, + RemoteJID: proto.String(portal.JID().String()), + FromMe: fromMe, + ID: &targetMsg.ID, Participant: messageKeyParticipant, } } @@ -963,8 +968,8 @@ func (portal *Portal) sendReaction(ctx context.Context, sender *User, targetMsg if !targetMsg.IsUnencrypted() { consumerMsg := wrapReaction(&waConsumerApplication.ConsumerApplication_ReactionMessage{ Key: portal.buildMessageKey(sender, targetMsg), - Text: metaEmoji, - SenderTimestampMS: timestamp, + Text: &metaEmoji, + SenderTimestampMS: ×tamp, }) resp, err := sender.E2EEClient.SendFBMessage(ctx, portal.JID(), consumerMsg, nil) zerolog.Ctx(ctx).Trace().Any("response", resp).Msg("WhatsApp reaction response") @@ -1462,7 +1467,7 @@ func (portal *Portal) handleMetaOrWhatsAppMessage(ctx context.Context, source *U func (portal *Portal) handleWhatsAppEditMessage(ctx context.Context, sender *Puppet, edit *waConsumerApplication.ConsumerApplication_EditMessage) { log := zerolog.Ctx(ctx).With(). - Int64("edit_ts", edit.TimestampMS). + Int64("edit_ts", edit.GetTimestampMS()). Logger() ctx = log.WithContext(context.TODO()) targetMsg, err := portal.bridge.DB.Message.GetAllPartsByID(ctx, edit.GetKey().GetID(), portal.Receiver) @@ -1475,16 +1480,16 @@ func (portal *Portal) handleWhatsAppEditMessage(ctx context.Context, sender *Pup } else if len(targetMsg) > 1 { log.Warn().Msg("Ignoring edit of multipart message") return - } else if targetMsg[0].EditTimestamp() >= edit.TimestampMS { + } else if targetMsg[0].EditTimestamp() >= edit.GetTimestampMS() { log.Debug().Int64("existing_edit_ts", targetMsg[0].EditTimestamp()).Msg("Ignoring duplicate edit") return } converted := portal.MsgConv.WhatsAppTextToMatrix(ctx, edit.GetMessage()) converted.Content.SetEdit(targetMsg[0].MXID) - resp, err := portal.sendMatrixEvent(ctx, sender.IntentFor(portal), converted.Type, converted.Content, converted.Extra, edit.TimestampMS) + resp, err := portal.sendMatrixEvent(ctx, sender.IntentFor(portal), converted.Type, converted.Content, converted.Extra, edit.GetTimestampMS()) if err != nil { log.Err(err).Msg("Failed to send edit to Matrix") - } else if err := targetMsg[0].UpdateEditTimestamp(ctx, edit.TimestampMS); err != nil { + } else if err := targetMsg[0].UpdateEditTimestamp(ctx, edit.GetTimestampMS()); err != nil { log.Err(err).Stringer("event_id", resp.EventID).Msg("Failed to save message edit count to database") } else { log.Debug().Stringer("event_id", resp.EventID).Msg("Handled Meta message edit")