Update dependencies and build to go1.22 (#2113)

* Update dependencies and build to go1.22

* Fix api changes wrt to dependencies

* Update golangci config
This commit is contained in:
Wim
2024-05-23 23:44:31 +02:00
committed by GitHub
parent 56e7bd01ca
commit 2f33fe86f5
1556 changed files with 3279522 additions and 1924375 deletions

View File

@@ -8,6 +8,8 @@ package whatsmeow
import (
"context"
"crypto/hmac"
"crypto/sha256"
"encoding/binary"
"fmt"
"time"
@@ -19,6 +21,10 @@ import (
"google.golang.org/protobuf/proto"
waBinary "go.mau.fi/whatsmeow/binary"
"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/binary/armadillo/waMsgTransport"
waProto "go.mau.fi/whatsmeow/binary/proto"
"go.mau.fi/whatsmeow/types"
"go.mau.fi/whatsmeow/types/events"
@@ -32,19 +38,22 @@ type recentMessageKey struct {
ID types.MessageID
}
// RecentMessage contains the info needed to re-send a message when another device fails to decrypt it.
type RecentMessage struct {
Proto *waProto.Message
Timestamp time.Time
wa *waProto.Message
fb *waMsgApplication.MessageApplication
}
func (cli *Client) addRecentMessage(to types.JID, id types.MessageID, message *waProto.Message) {
func (rm RecentMessage) IsEmpty() bool {
return rm.wa == nil && rm.fb == nil
}
func (cli *Client) addRecentMessage(to types.JID, id types.MessageID, wa *waProto.Message, fb *waMsgApplication.MessageApplication) {
cli.recentMessagesLock.Lock()
key := recentMessageKey{to, id}
if cli.recentMessagesList[cli.recentMessagesPtr].ID != "" {
delete(cli.recentMessagesMap, cli.recentMessagesList[cli.recentMessagesPtr])
}
cli.recentMessagesMap[key] = message
cli.recentMessagesMap[key] = RecentMessage{wa: wa, fb: fb}
cli.recentMessagesList[cli.recentMessagesPtr] = key
cli.recentMessagesPtr++
if cli.recentMessagesPtr >= len(cli.recentMessagesList) {
@@ -53,26 +62,27 @@ func (cli *Client) addRecentMessage(to types.JID, id types.MessageID, message *w
cli.recentMessagesLock.Unlock()
}
func (cli *Client) getRecentMessage(to types.JID, id types.MessageID) *waProto.Message {
func (cli *Client) getRecentMessage(to types.JID, id types.MessageID) RecentMessage {
cli.recentMessagesLock.RLock()
msg, _ := cli.recentMessagesMap[recentMessageKey{to, id}]
cli.recentMessagesLock.RUnlock()
return msg
}
func (cli *Client) getMessageForRetry(receipt *events.Receipt, messageID types.MessageID) (*waProto.Message, error) {
func (cli *Client) getMessageForRetry(receipt *events.Receipt, messageID types.MessageID) (RecentMessage, error) {
msg := cli.getRecentMessage(receipt.Chat, messageID)
if msg == nil {
msg = cli.GetMessageForRetry(receipt.Sender, receipt.Chat, messageID)
if msg == nil {
return nil, fmt.Errorf("couldn't find message %s", messageID)
if msg.IsEmpty() {
waMsg := cli.GetMessageForRetry(receipt.Sender, receipt.Chat, messageID)
if waMsg == nil {
return RecentMessage{}, fmt.Errorf("couldn't find message %s", messageID)
} else {
cli.Log.Debugf("Found message in GetMessageForRetry to accept retry receipt for %s/%s from %s", receipt.Chat, messageID, receipt.Sender)
}
msg = RecentMessage{wa: waMsg}
} else {
cli.Log.Debugf("Found message in local cache to accept retry receipt for %s/%s from %s", receipt.Chat, messageID, receipt.Sender)
}
return proto.Clone(msg).(*waProto.Message), nil
return msg, nil
}
const recreateSessionTimeout = 1 * time.Hour
@@ -94,6 +104,11 @@ func (cli *Client) shouldRecreateSession(retryCount int, jid types.JID) (reason
return "", false
}
type incomingRetryKey struct {
jid types.JID
messageID types.MessageID
}
// handleRetryReceipt handles an incoming retry receipt for an outgoing message.
func (cli *Client) handleRetryReceipt(receipt *events.Receipt, node *waBinary.Node) error {
retryChild, ok := node.GetOptionalChildByTag("retry")
@@ -111,40 +126,87 @@ func (cli *Client) handleRetryReceipt(receipt *events.Receipt, node *waBinary.No
if err != nil {
return err
}
var fbConsumerMsg *waConsumerApplication.ConsumerApplication
if msg.fb != nil {
subProto, ok := msg.fb.GetPayload().GetSubProtocol().GetSubProtocol().(*waMsgApplication.MessageApplication_SubProtocolPayload_ConsumerMessage)
if ok {
fbConsumerMsg, err = subProto.Decode()
if err != nil {
return fmt.Errorf("failed to decode consumer message for retry: %w", err)
}
}
}
retryKey := incomingRetryKey{receipt.Sender, messageID}
cli.incomingRetryRequestCounterLock.Lock()
cli.incomingRetryRequestCounter[retryKey]++
internalCounter := cli.incomingRetryRequestCounter[retryKey]
cli.incomingRetryRequestCounterLock.Unlock()
if internalCounter >= 10 {
cli.Log.Warnf("Dropping retry request from %s for %s: internal retry counter is %d", messageID, receipt.Sender, internalCounter)
return nil
}
ownID := cli.getOwnID()
if ownID.IsEmpty() {
return ErrNotLoggedIn
}
var fbSKDM *waMsgTransport.MessageTransport_Protocol_Ancillary_SenderKeyDistributionMessage
var fbDSM *waMsgTransport.MessageTransport_Protocol_Integral_DeviceSentMessage
if receipt.IsGroup {
builder := groups.NewGroupSessionBuilder(cli.Store, pbSerializer)
senderKeyName := protocol.NewSenderKeyName(receipt.Chat.String(), ownID.SignalAddress())
signalSKDMessage, err := builder.Create(senderKeyName)
if err != nil {
cli.Log.Warnf("Failed to create sender key distribution message to include in retry of %s in %s to %s: %v", messageID, receipt.Chat, receipt.Sender, err)
} else {
msg.SenderKeyDistributionMessage = &waProto.SenderKeyDistributionMessage{
}
if msg.wa != nil {
msg.wa.SenderKeyDistributionMessage = &waProto.SenderKeyDistributionMessage{
GroupId: proto.String(receipt.Chat.String()),
AxolotlSenderKeyDistributionMessage: signalSKDMessage.Serialize(),
}
} else {
fbSKDM = &waMsgTransport.MessageTransport_Protocol_Ancillary_SenderKeyDistributionMessage{
GroupID: receipt.Chat.String(),
AxolotlSenderKeyDistributionMessage: signalSKDMessage.Serialize(),
}
}
} else if receipt.IsFromMe {
msg = &waProto.Message{
DeviceSentMessage: &waProto.DeviceSentMessage{
DestinationJid: proto.String(receipt.Chat.String()),
Message: msg,
},
if msg.wa != nil {
msg.wa = &waProto.Message{
DeviceSentMessage: &waProto.DeviceSentMessage{
DestinationJid: proto.String(receipt.Chat.String()),
Message: msg.wa,
},
}
} else {
fbDSM = &waMsgTransport.MessageTransport_Protocol_Integral_DeviceSentMessage{
DestinationJID: receipt.Chat.String(),
}
}
}
if cli.PreRetryCallback != nil && !cli.PreRetryCallback(receipt, messageID, retryCount, msg) {
// TODO pre-retry callback for fb
if cli.PreRetryCallback != nil && !cli.PreRetryCallback(receipt, messageID, retryCount, msg.wa) {
cli.Log.Debugf("Cancelled retry receipt in PreRetryCallback")
return nil
}
plaintext, err := proto.Marshal(msg)
if err != nil {
return fmt.Errorf("failed to marshal message: %w", err)
var plaintext, frankingTag []byte
if msg.wa != nil {
plaintext, err = proto.Marshal(msg.wa)
if err != nil {
return fmt.Errorf("failed to marshal message: %w", err)
}
} else {
plaintext, err = proto.Marshal(msg.fb)
if err != nil {
return fmt.Errorf("failed to marshal consumer message: %w", err)
}
frankingHash := hmac.New(sha256.New, msg.fb.GetMetadata().GetFrankingKey())
frankingHash.Write(plaintext)
frankingTag = frankingHash.Sum(nil)
}
_, hasKeys := node.GetOptionalChildByTag("keys")
var bundle *prekey.Bundle
@@ -160,20 +222,39 @@ func (cli *Client) handleRetryReceipt(receipt *events.Receipt, node *waBinary.No
if err != nil {
return err
}
senderAD := receipt.Sender
senderAD.AD = true
bundle, err = keys[senderAD].bundle, keys[senderAD].err
bundle, err = keys[receipt.Sender].bundle, keys[receipt.Sender].err
if err != nil {
return fmt.Errorf("failed to fetch prekeys: %w", err)
} else if bundle == nil {
return fmt.Errorf("didn't get prekey bundle for %s (response size: %d)", senderAD, len(keys))
return fmt.Errorf("didn't get prekey bundle for %s (response size: %d)", receipt.Sender, len(keys))
}
}
encAttrs := waBinary.Attrs{}
if mediaType := getMediaTypeFromMessage(msg); mediaType != "" {
encAttrs["mediatype"] = mediaType
var msgAttrs messageAttrs
if msg.wa != nil {
msgAttrs.MediaType = getMediaTypeFromMessage(msg.wa)
msgAttrs.Type = getTypeFromMessage(msg.wa)
} else if fbConsumerMsg != nil {
msgAttrs = getAttrsFromFBMessage(fbConsumerMsg)
} else {
msgAttrs.Type = "text"
}
if msgAttrs.MediaType != "" {
encAttrs["mediatype"] = msgAttrs.MediaType
}
var encrypted *waBinary.Node
var includeDeviceIdentity bool
if msg.wa != nil {
encrypted, includeDeviceIdentity, err = cli.encryptMessageForDevice(plaintext, receipt.Sender, bundle, encAttrs)
} else {
encrypted, err = cli.encryptMessageForDeviceV3(&waMsgTransport.MessageTransport_Payload{
ApplicationPayload: &waCommon.SubProtocol{
Payload: plaintext,
Version: FBMessageApplicationVersion,
},
FutureProof: waCommon.FutureProofBehavior_PLACEHOLDER,
}, fbSKDM, fbDSM, receipt.Sender, bundle, encAttrs)
}
encrypted, includeDeviceIdentity, err := cli.encryptMessageForDevice(plaintext, receipt.Sender, bundle, encAttrs)
if err != nil {
return fmt.Errorf("failed to encrypt message for retry: %w", err)
}
@@ -181,7 +262,7 @@ func (cli *Client) handleRetryReceipt(receipt *events.Receipt, node *waBinary.No
attrs := waBinary.Attrs{
"to": node.Attrs["from"],
"type": getTypeFromMessage(msg),
"type": msgAttrs.Type,
"id": messageID,
"t": timestamp.Unix(),
}
@@ -197,10 +278,19 @@ func (cli *Client) handleRetryReceipt(receipt *events.Receipt, node *waBinary.No
if edit, ok := node.Attrs["edit"]; ok {
attrs["edit"] = edit
}
var content []waBinary.Node
if msg.wa != nil {
content = cli.getMessageContent(*encrypted, msg.wa, attrs, includeDeviceIdentity)
} else {
content = []waBinary.Node{
*encrypted,
{Tag: "franking", Content: []waBinary.Node{{Tag: "franking_tag", Content: frankingTag}}},
}
}
err = cli.sendNode(waBinary.Node{
Tag: "message",
Attrs: attrs,
Content: cli.getMessageContent(*encrypted, msg, attrs, includeDeviceIdentity),
Content: content,
})
if err != nil {
return fmt.Errorf("failed to send retry message: %w", err)
@@ -210,7 +300,7 @@ func (cli *Client) handleRetryReceipt(receipt *events.Receipt, node *waBinary.No
}
func (cli *Client) cancelDelayedRequestFromPhone(msgID types.MessageID) {
if !cli.AutomaticMessageRerequestFromPhone {
if !cli.AutomaticMessageRerequestFromPhone || cli.MessengerConfig != nil {
return
}
cli.pendingPhoneRerequestsLock.RLock()
@@ -226,7 +316,7 @@ func (cli *Client) cancelDelayedRequestFromPhone(msgID types.MessageID) {
var RequestFromPhoneDelay = 5 * time.Second
func (cli *Client) delayedRequestMessageFromPhone(info *types.MessageInfo) {
if !cli.AutomaticMessageRerequestFromPhone {
if !cli.AutomaticMessageRerequestFromPhone || cli.MessengerConfig != nil {
return
}
cli.pendingPhoneRerequestsLock.Lock()
@@ -253,7 +343,7 @@ func (cli *Client) delayedRequestMessageFromPhone(info *types.MessageInfo) {
}
_, err := cli.SendMessage(
ctx,
cli.Store.ID.ToNonAD(),
cli.getOwnID().ToNonAD(),
cli.BuildUnavailableMessageRequest(info.Chat, info.Sender, info.ID),
SendRequestExtra{Peer: true},
)