Compare commits

...
42 Commits
Author SHA1 Message Date
Alexandre Possebom 19bd3a9126 client: ack channel <status> stanzas to stop 50-minute stream recycling
Go / Build (latest) (push) Failing after 5m18s
Go / Build (old) (push) Failing after 5m18s
The server delivers channel status updates as <status> stanzas. Without a
registered node handler they were dropped unacked, so the server redelivered
them on every connect and closed the stream every 50 minutes with
<stream:error><ack class="status" .../></stream:error>.
2026-07-15 18:02:16 -03:00
Tulir Asokan d8960d9575 user: fix parsing not on whatsapp responses 2026-07-13 14:28:32 +03:00
Tulir Asokan 592721a00b call: remove tctoken in reject requests
Fixes #1182
2026-07-13 14:20:39 +03:00
Tulir Asokan 37a86e6743 pair: parse client props 2026-07-13 14:14:17 +03:00
Tulir Asokan 6e4c341610 user: update IsOnWhatsApp query 2026-07-13 14:14:17 +03:00
Tulir Asokan 4f8f64e0dd send: always use LID for DMs 2026-07-13 14:14:17 +03:00
Tulir Asokan ebde598a59 proto: update to v1043045417 2026-07-13 13:37:19 +03:00
Tulir Asokan 73fe7355f5 msgsecret: add log to see if orig sender hack is used 2026-07-09 12:20:57 +03:00
Tulir Asokan b572e5bcb9 pair: add support for passkeys 2026-06-30 21:06:29 +03:00
Tulir Asokan 37913c82b7 proto: update to v1042386815 2026-06-30 16:30:29 +03:00
Tulir Asokan 5f04eac6db client: ignore connect success before pairing is completed 2026-06-22 21:54:15 +03:00
Tulir Asokan c50f490413 tctoken: return error in ensureTCToken if not logged in 2026-06-22 21:17:28 +03:00
Tulir Asokan e94c58afd4 proto: update to v1041871181 2026-06-22 15:45:18 +03:00
Tulir Asokan c833019767 notification: handle timelock mex notifications 2026-06-22 15:45:15 +03:00
Tulir Asokan 00ce57f21b call,group,user: add tctokens to more requests 2026-06-22 14:29:25 +03:00
Tulir Asokan 5eeb02b11f cstoken: remove unnecessary checks 2026-06-22 14:11:01 +03:00
Tulir Asokan eaa388b4e5 dependencies: update 2026-06-16 15:06:36 +03:00
Mahesa 089932318b docs: update sqlstore.New example to include context parameter (#1133) 2026-06-11 12:47:16 +03:00
Tulir Asokan ae2789723a all: replace interface{} with any
Closes #1172
2026-06-11 12:44:10 +03:00
Tulir Asokan 0ff50824f6 binary/xml: replace XMLString with standard String method
Closes #1170
2026-06-11 12:43:07 +03:00
Tulir Asokan 3706a7d315 send: ignore own device in all cases
Closes #1167
2026-06-11 11:51:19 +03:00
Tulir Asokan 4e622162b9 client: fix parsing own web message info in LID chats 2026-06-09 12:16:26 +03:00
Tulir Asokan 88b76e56e5 sqlstore: close container in New if upgrade fails 2026-06-09 12:13:05 +03:00
Tulir Asokan c6a4b703e4 proto: update to v1040847988 2026-06-04 23:57:42 +03:00
Tulir Asokan b10b70708a socket: use more atomic in FrameSocket
Closes #1150
Fixes #1085
2026-06-04 23:55:48 +03:00
Tulir Asokan d707fc25c5 download: remove file length checks and always check plaintext hash 2026-06-04 23:55:48 +03:00
Tulir Asokan 52afebe984 download: add flag to indicate whether hash should be required 2026-06-04 23:55:48 +03:00
Mohd Salman db52b2c73d group: make group creation time optional (#1136) 2026-06-04 23:53:59 +03:00
Tulir Asokan 256f4d77fb qrchan: update to atomic bool and listen for all disconnects
Fixes #856
2026-06-04 22:12:53 +03:00
Tulir Asokan 4216bd2e3c sqlstore: switch to rowiters for scanning many rows
Closes #1161
2026-06-04 22:12:53 +03:00
Tulir Asokan 6a7ac99153 download: check unencrypted file checksums 2026-06-03 16:24:17 +03:00
Tulir Asokan 595ceb0c22 message: handle historical message secrets and privacy tokens in LID chats 2026-06-02 20:39:33 +03:00
Tulir Asokan 9ff5508a26 download: remove support for legacy urls
Hopefully the problems from 2da9e916ba are no longer present
2026-06-01 01:03:58 +03:00
Tulir Asokan a7ea56383e message: ensure all nodes get acked 2026-05-29 13:19:37 +03:00
Tulir Asokan c404e9aba4 client: close node handler channel instead of sending struct 2026-05-29 13:13:07 +03:00
Tulir Asokan f87a9c5bf7 proto: update to v1040390703 2026-05-29 13:11:12 +03:00
Tulir Asokan fb137f8444 dependencies: update 2026-05-29 13:10:07 +03:00
Tulir Asokan 563bcaa0f6 sqlstore/lidmap: delete old map entries when LID or phone number changes 2026-05-25 17:41:32 +03:00
Tulir Asokan 933deb5f2e update: bump user agent for fetching latest version 2026-05-25 15:32:51 +03:00
Tulir Asokan 3e7fbac962 proto: update to v1040098269 2026-05-25 15:32:15 +03:00
Tulir Asokan 7c107215fa user,group,newsletter: strip query params when parsing links 2026-05-25 15:31:19 +03:00
Tulir Asokan 8d3700152a dependencies: update 2026-05-16 13:23:57 +03:00
69 changed files with 7255 additions and 3061 deletions

No files matched your search

+2 -2
View File
@@ -565,9 +565,9 @@ func (cli *Client) sendAppState(ctx context.Context, patch appstate.PatchInfo, a
if respCollectionAttr.OptionalString("type") == "error" {
errorTag, ok := respCollection.GetOptionalChildByTag("error")
mainErr := fmt.Errorf("%w: %s", ErrAppStateUpdate, respCollection.XMLString())
mainErr := fmt.Errorf("%w: %s", ErrAppStateUpdate, &respCollection)
if ok {
mainErr = fmt.Errorf("%w (%s): %s", ErrAppStateUpdate, patch.Type, errorTag.XMLString())
mainErr = fmt.Errorf("%w (%s): %s", ErrAppStateUpdate, patch.Type, &errorTag)
}
if ok && errorTag.AttrGetter().Int("code") == 409 && allowRetry {
zerolog.Ctx(ctx).Warn().Err(mainErr).Msg("Failed to update app state, trying to apply conflicts and retry")
+4 -1
View File
@@ -66,6 +66,8 @@ const (
IndexCustomerData = "customer_data"
IndexThreadPin = "thread_pin"
IndexSettingAutoOrganizeBusinessChat = "setting_autoOrganizeBusinessChat"
IndexCoexV2Version = "coexV2Version"
IndexLockMessage = "lock_message"
)
// Constants for the regular app state indexes.
@@ -121,7 +123,8 @@ const (
IndexPrivateProcessingSetting = "private_processing_setting"
IndexAIThreadDelete = "ai_thread_delete"
IndexNCTSaltSync = "nct_salt_sync"
IndexBizAISettingsNudgeAction = "biz_ai_settings_nudge_action"
IndexBizAISettingsNudgeAction = "biz_ai_settings_nudge"
IndexWasaRootSecretAction = "wasa_root_secret"
)
// Constants for the critical_unblock_low app state indexes.
+2 -2
View File
@@ -30,7 +30,7 @@ func (n *Node) AttrGetter() *AttrUtility {
}
func (au *AttrUtility) GetJID(key string, require bool) (jidVal types.JID, ok bool) {
var val interface{}
var val any
if val, ok = au.Attrs[key]; !ok {
if require {
au.Errors = append(au.Errors, fmt.Errorf("didn't find required JID attribute '%s'", key))
@@ -69,7 +69,7 @@ func (au *AttrUtility) JID(key string) types.JID {
}
func (au *AttrUtility) GetString(key string, require bool) (strVal string, ok bool) {
var val interface{}
var val any
if val, ok = au.Attrs[key]; !ok {
if require {
au.Errors = append(au.Errors, fmt.Errorf("didn't find required attribute '%s'", key))
+6 -6
View File
@@ -165,7 +165,7 @@ func (r *binaryDecoder) readListSize(tag int) (int, error) {
}
}
func (r *binaryDecoder) read(string bool) (interface{}, error) {
func (r *binaryDecoder) read(string bool) (any, error) {
tagByte, err := r.readByte()
if err != nil {
return nil, err
@@ -222,7 +222,7 @@ func (r *binaryDecoder) read(string bool) (interface{}, error) {
}
}
func (r *binaryDecoder) readJIDPair() (interface{}, error) {
func (r *binaryDecoder) readJIDPair() (any, error) {
user, err := r.read(true)
if err != nil {
return nil, err
@@ -238,7 +238,7 @@ func (r *binaryDecoder) readJIDPair() (interface{}, error) {
return types.NewJID(user.(string), server.(string)), nil
}
func (r *binaryDecoder) readInteropJID() (interface{}, error) {
func (r *binaryDecoder) readInteropJID() (any, error) {
user, err := r.read(true)
if err != nil {
return nil, err
@@ -265,7 +265,7 @@ func (r *binaryDecoder) readInteropJID() (interface{}, error) {
}, nil
}
func (r *binaryDecoder) readFBJID() (interface{}, error) {
func (r *binaryDecoder) readFBJID() (any, error) {
user, err := r.read(true)
if err != nil {
return nil, err
@@ -287,7 +287,7 @@ func (r *binaryDecoder) readFBJID() (interface{}, error) {
}, nil
}
func (r *binaryDecoder) readADJID() (interface{}, error) {
func (r *binaryDecoder) readADJID() (any, error) {
agent, err := r.readByte()
if err != nil {
return nil, err
@@ -383,7 +383,7 @@ func (r *binaryDecoder) readNode() (*Node, error) {
return ret, err
}
func (r *binaryDecoder) readBytesOrString(length int, asString bool) (interface{}, error) {
func (r *binaryDecoder) readBytesOrString(length int, asString bool) (any, error) {
data, err := r.readRaw(length)
if err != nil {
return nil, err
+1 -1
View File
@@ -98,7 +98,7 @@ func (w *binaryEncoder) writeNode(n Node) {
}
}
func (w *binaryEncoder) write(data interface{}) {
func (w *binaryEncoder) write(data any) {
switch typedData := data.(type) {
case nil:
w.pushByte(token.ListEmpty)
+3 -3
View File
@@ -19,9 +19,9 @@ type Attrs = map[string]any
// Node represents an XML element.
type Node struct {
Tag string // The tag of the element.
Attrs Attrs // The attributes of the element.
Content interface{} // The content inside the element. Can be nil, a list of Nodes, or a byte array.
Tag string // The tag of the element.
Attrs Attrs // The attributes of the element.
Content any // The content inside the element. Can be nil, a list of Nodes, or a byte array.
}
type marshalableNode struct {
+4 -4
View File
@@ -15,14 +15,14 @@ import (
"unicode/utf8"
)
// Options to control how Node.XMLString behaves.
// Options to control how Node.String behaves.
var (
IndentXML = false
MaxBytesToPrintAsHex = 128
)
// XMLString converts the Node to its XML representation
func (n *Node) XMLString() string {
// String converts the Node to its XML representation
func (n Node) String() string {
content := n.contentString()
if len(content) == 0 {
return fmt.Sprintf("<%[1]s%[2]s/>", n.Tag, n.attributeString())
@@ -66,7 +66,7 @@ func (n *Node) contentString() []string {
switch content := n.Content.(type) {
case []Node:
for _, item := range content {
split = append(split, strings.Split(item.XMLString(), "\n")...)
split = append(split, strings.Split(item.String(), "\n")...)
}
case []byte:
if strContent := printable(content); len(strContent) > 0 {
+8 -7
View File
@@ -109,13 +109,14 @@ func (cli *Client) RejectCall(ctx context.Context, callFrom types.JID, callID st
return ErrNotLoggedIn
}
ownID, callFrom = ownID.ToNonAD(), callFrom.ToNonAD()
rejectNode := waBinary.Node{
Tag: "reject",
Attrs: waBinary.Attrs{"call-id": callID, "call-creator": callFrom, "count": "0"},
Content: nil,
}
return cli.sendNode(ctx, waBinary.Node{
Tag: "call",
Attrs: waBinary.Attrs{"id": cli.GenerateMessageID(), "from": ownID, "to": callFrom},
Content: []waBinary.Node{{
Tag: "reject",
Attrs: waBinary.Attrs{"call-id": callID, "call-creator": callFrom, "count": "0"},
Content: nil,
}},
Tag: "call",
Attrs: waBinary.Attrs{"id": cli.GenerateMessageID(), "from": ownID, "to": callFrom},
Content: []waBinary.Node{rejectNode},
})
}
+25 -15
View File
@@ -70,6 +70,7 @@ type Client struct {
socketWait chan struct{}
isLoggedIn atomic.Bool
paired atomic.Bool
expectedDisconnect *exsync.Event
forceAutoReconnect atomic.Bool
EnableAutoReconnect bool
@@ -185,7 +186,10 @@ type Client struct {
BackgroundEventCtx context.Context
phoneLinkingCache *phoneLinkingCache
phoneLinkingCache atomic.Pointer[phoneLinkingCache]
passkeyLinkingCache atomic.Pointer[passkeyLinkingCache]
passkeyHandoffKey atomic.Pointer[passkeyHandoffKey]
passkeySkipHandoffUX atomic.Bool
uniqueID string
idCounter atomic.Uint64
@@ -227,7 +231,7 @@ const handlerQueueSize = 2048
//
// The device store must be set. A default SQL-backed implementation is available in the store/sqlstore package.
//
// container, err := sqlstore.New("sqlite3", "file:yoursqlitefile.db?_foreign_keys=on", nil)
// container, err := sqlstore.New(context.Background(), "sqlite3", "file:yoursqlitefile.db?_foreign_keys=on", nil)
// if err != nil {
// panic(err)
// }
@@ -282,6 +286,7 @@ func NewClient(deviceStore *store.Device, log waLog.Logger) *Client {
BackgroundEventCtx: context.Background(),
}
cli.paired.Store(deviceStore.ID != nil)
cli.nodeHandlers = map[string]nodeHandler{
"message": cli.handleEncryptedMessage,
"appdata": cli.handleEncryptedMessage,
@@ -290,6 +295,7 @@ func NewClient(deviceStore *store.Device, log waLog.Logger) *Client {
"chatstate": cli.handleChatState,
"presence": cli.handlePresence,
"notification": cli.handleNotification,
"status": cli.handleStatusUpdate,
"success": cli.handleConnectSuccess,
"failure": cli.handleConnectFailure,
"stream:error": cli.handleStreamError,
@@ -736,7 +742,7 @@ func (cli *Client) Logout(ctx context.Context) error {
// All registered event handlers will receive all events. You should use a type switch statement to
// filter the events you want:
//
// func myEventHandler(evt interface{}) {
// func myEventHandler(evt any) {
// switch v := evt.(type) {
// case *events.Message:
// fmt.Println("Received a message!")
@@ -757,7 +763,7 @@ func (cli *Client) Logout(ctx context.Context) error {
// mycli.eventHandlerID = mycli.WAClient.AddEventHandler(mycli.myEventHandler)
// }
//
// func (mycli *MyClient) myEventHandler(evt interface{}) {
// func (mycli *MyClient) myEventHandler(evt any) {
// // Handle event and access mycli.WAClient
// }
func (cli *Client) AddEventHandler(handler EventHandler) uint32 {
@@ -782,7 +788,7 @@ func (cli *Client) AddEventHandlerWithSuccessStatus(handler EventHandlerWithSucc
// event dispatcher holds a read lock on the event handler list, and this method wants a write lock
// on the same list. Instead run it in a goroutine:
//
// func (mycli *MyClient) myEventHandler(evt interface{}) {
// func (mycli *MyClient) myEventHandler(evt any) {
// if noLongerWantEvents {
// go mycli.WAClient.RemoveEventHandler(mycli.eventHandlerID)
// }
@@ -827,7 +833,7 @@ func (cli *Client) handleFrame(ctx context.Context, data []byte) {
cli.Log.Debugf("Errored frame hex: %s", hex.EncodeToString(decompressed))
return
}
cli.recvLog.Debugf("%s", node.XMLString())
cli.recvLog.Debugf("%s", node)
if node.Tag == "xmlstreamend" {
if !cli.isExpectedDisconnect() {
cli.Log.Warnf("Received stream end frame")
@@ -861,14 +867,14 @@ Loop:
for {
select {
case node := <-cli.handlerQueue:
doneChan := make(chan struct{}, 1)
doneChan := make(chan struct{})
start := time.Now()
go func() {
cli.nodeHandlers[node.Tag](evtCtx, node)
duration := time.Since(start)
doneChan <- struct{}{}
close(doneChan)
if duration > 5*time.Second {
cli.Log.Warnf("Node handling took %s for %s", duration, node.XMLString())
cli.Log.Warnf("Node handling took %s for %s", duration, node)
}
}()
ticker.Reset(30 * time.Second)
@@ -878,10 +884,10 @@ Loop:
ticker.Stop()
continue Loop
case <-ticker.C:
cli.Log.Warnf("Node handling is taking long for %s (started %s ago)", node.XMLString(), time.Since(start))
cli.Log.Warnf("Node handling is taking long for %s (started %s ago)", node, time.Since(start))
}
}
cli.Log.Warnf("Continuing handling of %s in background as it's taking too long", node.XMLString())
cli.Log.Warnf("Continuing handling of %s in background as it's taking too long", node)
ticker.Stop()
case <-connCtx.Done():
cli.Log.Debugf("Closing handler queue loop")
@@ -906,7 +912,7 @@ func (cli *Client) sendNodeAndGetData(ctx context.Context, node waBinary.Node) (
return nil, fmt.Errorf("failed to marshal node: %w", err)
}
cli.sendLog.Debugf("%s", node.XMLString())
cli.sendLog.Debugf("%s", &node)
return payload, sock.SendFrame(ctx, payload)
}
@@ -960,9 +966,13 @@ func (cli *Client) ParseWebMessage(chatJID types.JID, webMsg *waWeb.WebMessageIn
Timestamp: time.Unix(int64(webMsg.GetMessageTimestamp()), 0),
}
if info.IsFromMe {
info.Sender = cli.getOwnID().ToNonAD()
if info.Sender.IsEmpty() {
return nil, ErrNotLoggedIn
if webMsg.GetOriginalSelfAuthorUserJIDString() != "" {
info.Sender, err = types.ParseJID(webMsg.GetOriginalSelfAuthorUserJIDString())
} else {
info.Sender = cli.getOwnID().ToNonAD()
if info.Sender.IsEmpty() {
return nil, ErrNotLoggedIn
}
}
} else if chatJID.Server == types.DefaultUserServer || chatJID.Server == types.HiddenUserServer || chatJID.Server == types.NewsletterServer {
info.Sender = chatJID
+1 -1
View File
@@ -19,7 +19,7 @@ import (
waLog "go.mau.fi/whatsmeow/util/log"
)
func eventHandler(evt interface{}) {
func eventHandler(evt any) {
switch v := evt.(type) {
case *events.Message:
fmt.Println("Received a message!", v.Message.GetConversation())
+7 -3
View File
@@ -64,7 +64,7 @@ func (cli *Client) handleStreamError(ctx context.Context, node *waBinary.Node) {
go cli.dispatchEvent(&events.CATRefreshError{Error: err})
}
default:
cli.Log.Errorf("Unknown stream error: %s", node.XMLString())
cli.Log.Errorf("Unknown stream error: %s", node)
go cli.dispatchEvent(&events.StreamError{Code: code, Raw: node})
}
}
@@ -131,7 +131,7 @@ func (cli *Client) handleConnectFailure(ctx context.Context, node *waBinary.Node
cli.Log.Warnf("Failed to delete store after %d failure: %v", int(reason), err)
}
} else if reason == events.ConnectFailureTempBanned {
cli.Log.Warnf("Temporary ban connect failure: %s", node.XMLString())
cli.Log.Warnf("Temporary ban connect failure: %s", node)
go cli.dispatchEvent(&events.TemporaryBan{
Code: events.TempBanReason(ag.Int("code")),
Expire: time.Duration(ag.Int("expire")) * time.Second,
@@ -150,12 +150,16 @@ func (cli *Client) handleConnectFailure(ctx context.Context, node *waBinary.Node
} else if willAutoReconnect {
cli.Log.Warnf("Got %d/%s connect failure, assuming automatic reconnect will handle it", int(reason), message)
} else {
cli.Log.Warnf("Unknown connect failure: %s", node.XMLString())
cli.Log.Warnf("Unknown connect failure: %s", node)
go cli.dispatchEvent(&events.ConnectFailure{Reason: reason, Message: message, Raw: node})
}
}
func (cli *Client) handleConnectSuccess(ctx context.Context, node *waBinary.Node) {
if !cli.paired.Load() {
cli.Log.Warnf("Received connect success without pairing, ignoring")
return
}
cli.Log.Infof("Successfully authenticated")
cli.LastSuccessfulConnect = time.Now()
cli.AutoReconnectErrors = 0
+7 -13
View File
@@ -26,9 +26,6 @@ func (cli *Client) generateCsToken(ctx context.Context, jid types.JID) []byte {
if !shouldSendCsToken(jid) {
return nil
}
if cli.Store == nil || cli.Store.NCTSalt == nil {
return nil
}
salt, err := cli.Store.NCTSalt.GetNCTSalt(ctx)
if err != nil {
cli.Log.Debugf("Failed to load NCT salt for cstoken: %v", err)
@@ -42,9 +39,6 @@ func (cli *Client) generateCsToken(ctx context.Context, jid types.JID) []byte {
case types.HiddenUserServer:
recipientLID = jid.ToNonAD()
case types.DefaultUserServer:
if cli.Store == nil || cli.Store.LIDs == nil {
return nil
}
pn := jid.ToNonAD()
lid, err := cli.Store.LIDs.GetLIDForPN(ctx, pn)
if err != nil {
@@ -69,18 +63,18 @@ func (cli *Client) generateCsToken(ctx context.Context, jid types.JID) []byte {
}
func (cli *Client) storeNCTSalt(ctx context.Context, salt []byte) error {
if cli.Store == nil || cli.Store.NCTSalt == nil {
return nil
}
if len(salt) == 0 {
return nil
}
return cli.Store.NCTSalt.PutNCTSalt(ctx, salt)
err := cli.Store.NCTSalt.PutNCTSalt(ctx, salt)
if err != nil {
return err
}
cli.Log.Debugf("Stored new NCT salt")
return nil
}
func (cli *Client) clearNCTSalt(ctx context.Context) error {
if cli.Store == nil || cli.Store.NCTSalt == nil {
return nil
}
cli.Log.Debugf("Clearing NCT salt")
return cli.Store.NCTSalt.DeleteNCTSalt(ctx)
}
+43 -34
View File
@@ -46,23 +46,13 @@ func (cli *Client) DownloadToFile(ctx context.Context, msg DownloadableMessage,
if mediaType == "" {
return fmt.Errorf("%w %T", ErrUnknownMediaType, msg)
}
urlable, ok := msg.(downloadableMessageWithURL)
var url string
var isWebWhatsappNetURL bool
if ok {
url = urlable.GetURL()
isWebWhatsappNetURL = strings.HasPrefix(url, "https://web.whatsapp.net")
}
if len(url) > 0 && !isWebWhatsappNetURL {
return cli.downloadAndDecryptToFile(ctx, url, msg.GetMediaKey(), mediaType, getSize(msg), msg.GetFileEncSHA256(), msg.GetFileSHA256(), file)
} else if len(msg.GetDirectPath()) > 0 {
return cli.DownloadMediaWithPathToFile(ctx, msg.GetDirectPath(), msg.GetFileEncSHA256(), msg.GetFileSHA256(), msg.GetMediaKey(), getSize(msg), mediaType, mediaTypeToMMSType[mediaType], file)
} else {
if isWebWhatsappNetURL {
cli.Log.Warnf("Got a media message with a web.whatsapp.net URL (%s) and no direct path", url)
}
if len(msg.GetDirectPath()) == 0 {
return ErrNoURLPresent
}
return cli.DownloadMediaWithPathToFile(
ctx, msg.GetDirectPath(), msg.GetFileEncSHA256(), msg.GetFileSHA256(), msg.GetMediaKey(),
mediaType, mediaTypeToMMSType[mediaType], false, file,
)
}
func (cli *Client) DownloadFBToFile(
@@ -71,18 +61,31 @@ func (cli *Client) DownloadFBToFile(
mediaType MediaType,
file File,
) error {
return cli.DownloadMediaWithPathToFile(ctx, transport.GetDirectPath(), transport.GetFileEncSHA256(), transport.GetFileSHA256(), transport.GetMediaKey(), -1, mediaType, mediaTypeToMMSType[mediaType], file)
return cli.DownloadMediaWithPathToFile(
ctx, transport.GetDirectPath(), transport.GetFileEncSHA256(), transport.GetFileSHA256(), transport.GetMediaKey(),
mediaType, mediaTypeToMMSType[mediaType], false, file,
)
}
func (cli *Client) DownloadMediaWithOnlyPathToFile(ctx context.Context, directPath string, file File) error {
return cli.DownloadMediaWithPathToFile(ctx, directPath, nil, nil, nil, "", "", true, file)
}
func (cli *Client) DownloadMediaWithPathToFile(
ctx context.Context,
directPath string,
encFileHash, fileHash, mediaKey []byte,
fileLength int,
mediaType MediaType,
mmsType string,
allowNoHash bool,
file File,
) error {
if !allowNoHash && fileHash == nil {
fileHash = make([]byte, 32)
}
if !strings.HasPrefix(directPath, "/") {
return fmt.Errorf("media download path does not start with slash: %s", directPath)
}
mediaConn, err := cli.refreshMediaConn(ctx, false)
if err != nil {
return fmt.Errorf("failed to refresh media connections: %w", err)
@@ -93,9 +96,8 @@ func (cli *Client) DownloadMediaWithPathToFile(
for i, host := range mediaConn.Hosts {
// TODO omit hash for unencrypted media?
mediaURL := fmt.Sprintf("https://%s%s&hash=%s&mms-type=%s&__wa-mms=", host.Hostname, directPath, base64.URLEncoding.EncodeToString(encFileHash), mmsType)
err = cli.downloadAndDecryptToFile(ctx, mediaURL, mediaKey, mediaType, fileLength, encFileHash, fileHash, file)
err = cli.downloadAndDecryptToFile(ctx, mediaURL, mediaKey, mediaType, encFileHash, fileHash, file)
if err == nil ||
errors.Is(err, ErrFileLengthMismatch) ||
errors.Is(err, ErrInvalidMediaSHA256) ||
errors.Is(err, ErrMediaDownloadFailedWith403) ||
errors.Is(err, ErrMediaDownloadFailedWith404) ||
@@ -115,7 +117,6 @@ func (cli *Client) downloadAndDecryptToFile(
url string,
mediaKey []byte,
appInfo MediaType,
fileLength int,
fileEncSHA256, fileSHA256 []byte,
file File,
) error {
@@ -124,7 +125,18 @@ func (cli *Client) downloadAndDecryptToFile(
if mac, err := cli.downloadPossiblyEncryptedMediaWithRetriesToFile(ctx, url, fileEncSHA256, file); err != nil {
return err
} else if mediaKey == nil && fileEncSHA256 == nil && mac == nil {
// Unencrypted media, just return the downloaded data
// Unencrypted media, just check the hash and return
if fileSHA256 == nil {
return nil
}
_, err = file.Seek(0, io.SeekStart)
if err != nil {
return fmt.Errorf("failed to seek to start of file: %w", err)
} else if _, err = io.Copy(hasher, file); err != nil {
return fmt.Errorf("failed to hash file: %w", err)
} else if !hmac.Equal(fileSHA256, hasher.Sum(nil)) {
return ErrInvalidUnencryptedMediaSHA256
}
return nil
} else if err = validateMediaFile(file, iv, macKey, mac); err != nil {
return err
@@ -132,18 +144,12 @@ func (cli *Client) downloadAndDecryptToFile(
return fmt.Errorf("failed to seek to start of file after validating mac: %w", err)
} else if err = cbcutil.DecryptFile(cipherKey, iv, file); err != nil {
return fmt.Errorf("failed to decrypt file: %w", err)
} else if ReturnDownloadWarnings {
if info, err := file.Stat(); err != nil {
return fmt.Errorf("failed to stat file: %w", err)
} else if fileLength >= 0 && info.Size() != int64(fileLength) {
return fmt.Errorf("%w: expected %d, got %d", ErrFileLengthMismatch, fileLength, info.Size())
} else if _, err = file.Seek(0, io.SeekStart); err != nil {
return fmt.Errorf("failed to seek to start of file after decrypting: %w", err)
} else if _, err = io.Copy(hasher, file); err != nil {
return fmt.Errorf("failed to hash file: %w", err)
} else if !hmac.Equal(fileSHA256, hasher.Sum(nil)) {
return ErrInvalidMediaSHA256
}
} else if _, err = file.Seek(0, io.SeekStart); err != nil {
return fmt.Errorf("failed to seek to start of file after decrypting: %w", err)
} else if _, err = io.Copy(hasher, file); err != nil {
return fmt.Errorf("failed to hash file: %w", err)
} else if !hmac.Equal(fileSHA256, hasher.Sum(nil)) {
return ErrInvalidMediaSHA256
}
return nil
}
@@ -196,12 +202,15 @@ func (cli *Client) downloadMediaToFile(ctx context.Context, url string, file io.
}
func (cli *Client) downloadEncryptedMediaToFile(ctx context.Context, url string, checksum []byte, file File) ([]byte, error) {
if len(checksum) != 32 {
return nil, fmt.Errorf("invalid checksum length: expected 32, got %d", len(checksum))
}
size, hash, err := cli.downloadMediaToFile(ctx, url, file)
if err != nil {
return nil, err
} else if size <= mediaHMACLength {
return nil, ErrTooShortFile
} else if len(checksum) == 32 && !hmac.Equal(checksum, hash) {
} else if checksum != nil && !hmac.Equal(checksum, hash) {
return nil, ErrInvalidMediaEncSHA256
}
mac := make([]byte, mediaHMACLength)
+32 -59
View File
@@ -92,21 +92,6 @@ var (
_ DownloadableMessage = (*types.StickerPackItem)(nil)
)
type downloadableMessageWithLength interface {
DownloadableMessage
GetFileLength() uint64
}
type downloadableMessageWithSizeBytes interface {
DownloadableMessage
GetFileSizeBytes() uint64
}
type downloadableMessageWithURL interface {
DownloadableMessage
GetURL() string
}
var classToMediaType = map[protoreflect.Name]MediaType{
"ImageMessage": MediaImage,
"AudioMessage": MediaAudio,
@@ -159,21 +144,6 @@ func (cli *Client) DownloadAny(ctx context.Context, msg *waE2E.Message) (data []
}
}
func getSize(msg DownloadableMessage) int {
switch sized := msg.(type) {
case downloadableMessageWithLength:
return int(sized.GetFileLength())
case downloadableMessageWithSizeBytes:
return int(sized.GetFileSizeBytes())
default:
return -1
}
}
// ReturnDownloadWarnings controls whether the Download function returns non-fatal validation warnings.
// Currently, these include [ErrFileLengthMismatch] and [ErrInvalidMediaSHA256].
var ReturnDownloadWarnings = true
// DownloadThumbnail downloads a thumbnail from a message.
//
// This is primarily intended for downloading link preview thumbnails, which are in ExtendedTextMessage:
@@ -186,7 +156,10 @@ func (cli *Client) DownloadThumbnail(ctx context.Context, msg DownloadableThumbn
if !ok {
return nil, fmt.Errorf("%w '%s'", ErrUnknownMediaType, string(msg.ProtoReflect().Descriptor().Name()))
} else if len(msg.GetThumbnailDirectPath()) > 0 {
return cli.DownloadMediaWithPath(ctx, msg.GetThumbnailDirectPath(), msg.GetThumbnailEncSHA256(), msg.GetThumbnailSHA256(), msg.GetMediaKey(), -1, mediaType, mediaTypeToMMSType[mediaType])
return cli.DownloadMediaWithPath(
ctx, msg.GetThumbnailDirectPath(), msg.GetThumbnailEncSHA256(), msg.GetThumbnailSHA256(), msg.GetMediaKey(),
mediaType, mediaTypeToMMSType[mediaType], false,
)
} else {
return nil, ErrNoURLPresent
}
@@ -240,23 +213,13 @@ func (cli *Client) Download(ctx context.Context, msg DownloadableMessage) ([]byt
if mediaType == "" {
return nil, fmt.Errorf("%w %T", ErrUnknownMediaType, msg)
}
urlable, ok := msg.(downloadableMessageWithURL)
var url string
var isWebWhatsappNetURL bool
if ok {
url = urlable.GetURL()
isWebWhatsappNetURL = strings.HasPrefix(url, "https://web.whatsapp.net")
}
if len(url) > 0 && !isWebWhatsappNetURL {
return cli.downloadAndDecrypt(ctx, url, msg.GetMediaKey(), mediaType, getSize(msg), msg.GetFileEncSHA256(), msg.GetFileSHA256())
} else if len(msg.GetDirectPath()) > 0 {
return cli.DownloadMediaWithPath(ctx, msg.GetDirectPath(), msg.GetFileEncSHA256(), msg.GetFileSHA256(), msg.GetMediaKey(), getSize(msg), mediaType, mediaTypeToMMSType[mediaType])
} else {
if isWebWhatsappNetURL {
cli.Log.Warnf("Got a media message with a web.whatsapp.net URL (%s) and no direct path", url)
}
if len(msg.GetDirectPath()) == 0 {
return nil, ErrNoURLPresent
}
return cli.DownloadMediaWithPath(
ctx, msg.GetDirectPath(), msg.GetFileEncSHA256(), msg.GetFileSHA256(), msg.GetMediaKey(),
mediaType, mediaTypeToMMSType[mediaType], false,
)
}
func (cli *Client) DownloadFB(
@@ -264,7 +227,14 @@ func (cli *Client) DownloadFB(
transport *waMediaTransport.WAMediaTransport_Integral,
mediaType MediaType,
) ([]byte, error) {
return cli.DownloadMediaWithPath(ctx, transport.GetDirectPath(), transport.GetFileEncSHA256(), transport.GetFileSHA256(), transport.GetMediaKey(), -1, mediaType, mediaTypeToMMSType[mediaType])
return cli.DownloadMediaWithPath(
ctx, transport.GetDirectPath(), transport.GetFileEncSHA256(), transport.GetFileSHA256(), transport.GetMediaKey(),
mediaType, mediaTypeToMMSType[mediaType], false,
)
}
func (cli *Client) DownloadMediaWithOnlyPath(ctx context.Context, directPath string) ([]byte, error) {
return cli.DownloadMediaWithPath(ctx, directPath, nil, nil, nil, "", "", true)
}
// DownloadMediaWithPath downloads an attachment by manually specifying the path and encryption details.
@@ -272,10 +242,13 @@ func (cli *Client) DownloadMediaWithPath(
ctx context.Context,
directPath string,
encFileHash, fileHash, mediaKey []byte,
fileLength int,
mediaType MediaType,
mmsType string,
allowNoHash bool,
) (data []byte, err error) {
if !allowNoHash && fileHash == nil {
fileHash = make([]byte, 32)
}
if !strings.HasPrefix(directPath, "/") {
return nil, fmt.Errorf("media download path does not start with slash: %s", directPath)
}
@@ -290,9 +263,8 @@ func (cli *Client) DownloadMediaWithPath(
for i, host := range mediaConn.Hosts {
// TODO omit hash for unencrypted media?
mediaURL := fmt.Sprintf("https://%s%s&hash=%s&mms-type=%s&__wa-mms=", host.Hostname, directPath, base64.URLEncoding.EncodeToString(encFileHash), mmsType)
data, err = cli.downloadAndDecrypt(ctx, mediaURL, mediaKey, mediaType, fileLength, encFileHash, fileHash)
data, err = cli.downloadAndDecrypt(ctx, mediaURL, mediaKey, mediaType, encFileHash, fileHash)
if err == nil ||
errors.Is(err, ErrFileLengthMismatch) ||
errors.Is(err, ErrInvalidMediaSHA256) ||
errors.Is(err, ErrMediaDownloadFailedWith403) ||
errors.Is(err, ErrMediaDownloadFailedWith404) ||
@@ -312,7 +284,6 @@ func (cli *Client) downloadAndDecrypt(
url string,
mediaKey []byte,
appInfo MediaType,
fileLength int,
fileEncSHA256,
fileSHA256 []byte,
) (data []byte, err error) {
@@ -321,18 +292,17 @@ func (cli *Client) downloadAndDecrypt(
if ciphertext, mac, err = cli.downloadPossiblyEncryptedMediaWithRetries(ctx, url, fileEncSHA256); err != nil {
} else if mediaKey == nil && fileEncSHA256 == nil && mac == nil {
// Unencrypted media, just return the downloaded data
// Unencrypted media, just check the hash and return
data = ciphertext
if fileSHA256 != nil && (len(fileSHA256) != 32 || sha256.Sum256(data) != *(*[32]byte)(fileSHA256)) {
err = ErrInvalidUnencryptedMediaSHA256
}
} else if err = validateMedia(iv, ciphertext, macKey, mac); err != nil {
} else if data, err = cbcutil.Decrypt(cipherKey, iv, ciphertext); err != nil {
err = fmt.Errorf("failed to decrypt file: %w", err)
} else if ReturnDownloadWarnings {
if fileLength >= 0 && len(data) != fileLength {
err = fmt.Errorf("%w: expected %d, got %d", ErrFileLengthMismatch, fileLength, len(data))
} else if len(fileSHA256) == 32 && sha256.Sum256(data) != *(*[32]byte)(fileSHA256) {
err = ErrInvalidMediaSHA256
}
} else if len(fileSHA256) != 32 || sha256.Sum256(data) != *(*[32]byte)(fileSHA256) {
err = ErrInvalidMediaSHA256
}
return
}
@@ -413,6 +383,9 @@ func (cli *Client) downloadMedia(ctx context.Context, url string) ([]byte, error
const mediaHMACLength = 10
func (cli *Client) downloadEncryptedMedia(ctx context.Context, url string, checksum []byte) (file, mac []byte, err error) {
if len(checksum) != 32 {
return nil, nil, fmt.Errorf("invalid checksum length: expected 32, got %d", len(checksum))
}
data, err := cli.downloadMedia(ctx, url)
if err != nil {
return
@@ -421,7 +394,7 @@ func (cli *Client) downloadEncryptedMedia(ctx context.Context, url string, check
return
}
file, mac = data[:len(data)-mediaHMACLength], data[len(data)-mediaHMACLength:]
if len(checksum) == 32 && sha256.Sum256(data) != *(*[32]byte)(checksum) {
if sha256.Sum256(data) != *(*[32]byte)(checksum) {
err = ErrInvalidMediaEncSHA256
}
return
+17 -14
View File
@@ -128,17 +128,20 @@ func (dhe DownloadHTTPError) Is(other error) bool {
// Some errors that Client.Download can return
var (
ErrMediaDownloadFailedWith403 = DownloadHTTPError{Response: &http.Response{StatusCode: 403}}
ErrMediaDownloadFailedWith404 = DownloadHTTPError{Response: &http.Response{StatusCode: 404}}
ErrMediaDownloadFailedWith410 = DownloadHTTPError{Response: &http.Response{StatusCode: 410}}
ErrNoURLPresent = errors.New("no url present")
ErrFileLengthMismatch = errors.New("file length does not match")
ErrTooShortFile = errors.New("file too short")
ErrInvalidMediaHMAC = errors.New("invalid media hmac")
ErrInvalidMediaEncSHA256 = errors.New("hash of media ciphertext doesn't match")
ErrInvalidMediaSHA256 = errors.New("hash of media plaintext doesn't match")
ErrUnknownMediaType = errors.New("unknown media type")
ErrNothingDownloadableFound = errors.New("didn't find any attachments in message")
ErrMediaDownloadFailedWith403 = DownloadHTTPError{Response: &http.Response{StatusCode: 403}}
ErrMediaDownloadFailedWith404 = DownloadHTTPError{Response: &http.Response{StatusCode: 404}}
ErrMediaDownloadFailedWith410 = DownloadHTTPError{Response: &http.Response{StatusCode: 410}}
ErrNoURLPresent = errors.New("no url present")
ErrTooShortFile = errors.New("file too short")
ErrInvalidMediaHMAC = errors.New("invalid media hmac")
ErrInvalidMediaEncSHA256 = errors.New("hash of media ciphertext doesn't match")
ErrInvalidMediaSHA256 = errors.New("hash of media plaintext doesn't match")
ErrInvalidUnencryptedMediaSHA256 = errors.New("hash of unencrypted media doesn't match")
ErrUnknownMediaType = errors.New("unknown media type")
ErrNothingDownloadableFound = errors.New("didn't find any attachments in message")
// Deprecated: this is no longer returned anywhere
ErrFileLengthMismatch = errors.New("file length does not match")
)
var (
@@ -211,9 +214,9 @@ func parseIQError(node *waBinary.Node) error {
func (iqe *IQError) Error() string {
if iqe.Code == 0 {
if iqe.ErrorNode != nil {
return fmt.Sprintf("info query returned unknown error: %s", iqe.ErrorNode.XMLString())
return fmt.Sprintf("info query returned unknown error: %s", iqe.ErrorNode)
} else if iqe.RawNode != nil {
return fmt.Sprintf("info query returned unexpected response: %s", iqe.RawNode.XMLString())
return fmt.Sprintf("info query returned unexpected response: %s", iqe.RawNode)
} else {
return "unknown info query error"
}
@@ -228,7 +231,7 @@ func (iqe *IQError) Is(other error) bool {
} else if iqe.Code != 0 && otherIQE.Code != 0 {
return otherIQE.Code == iqe.Code && otherIQE.Text == iqe.Text
} else if iqe.ErrorNode != nil && otherIQE.ErrorNode != nil {
return iqe.ErrorNode.XMLString() == otherIQE.ErrorNode.XMLString()
return iqe.ErrorNode.String() == otherIQE.ErrorNode.String()
} else {
return false
}
+12 -12
View File
@@ -2,29 +2,29 @@ module go.mau.fi/whatsmeow
go 1.25.0
toolchain go1.26.2
toolchain go1.26.4
require (
github.com/beeper/argo-go v1.1.2
github.com/coder/websocket v1.8.14
github.com/coder/websocket v1.8.15
github.com/google/uuid v1.6.0
github.com/rs/zerolog v1.35.0
go.mau.fi/libsignal v0.2.1
go.mau.fi/util v0.9.8
golang.org/x/crypto v0.50.0
golang.org/x/net v0.53.0
golang.org/x/sync v0.20.0
github.com/rs/zerolog v1.35.1
go.mau.fi/libsignal v0.2.2
go.mau.fi/util v0.9.10
golang.org/x/crypto v0.53.0
golang.org/x/net v0.56.0
golang.org/x/sync v0.21.0
google.golang.org/protobuf v1.36.11
)
require (
filippo.io/edwards25519 v1.1.0 // indirect
filippo.io/edwards25519 v1.2.0 // indirect
github.com/elliotchance/orderedmap/v3 v3.1.0 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/petermattis/goid v0.0.0-20260330135022-df67b199bc81 // indirect
github.com/vektah/gqlparser/v2 v2.5.27 // indirect
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f // indirect
golang.org/x/sys v0.43.0 // indirect
golang.org/x/text v0.36.0 // indirect
golang.org/x/exp v0.0.0-20260611194520-c48552f49976 // indirect
golang.org/x/sys v0.46.0 // indirect
golang.org/x/text v0.38.0 // indirect
)
+24 -24
View File
@@ -1,5 +1,5 @@
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
filippo.io/edwards25519 v1.2.0 h1:crnVqOiS4jqYleHd9vaKZ+HKtHfllngJIiOpNpoJsjo=
filippo.io/edwards25519 v1.2.0/go.mod h1:xzAOLCNug/yB62zG1bQ8uziwrIqIuxhctzJT18Q77mc=
github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
github.com/agnivade/levenshtein v1.2.1 h1:EHBY3UOn1gwdy/VbFwgo4cxecRznFk7fKWN1KOX7eoM=
@@ -8,8 +8,8 @@ github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNg
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
github.com/beeper/argo-go v1.1.2 h1:UQI2G8F+NLfGTOmTUI0254pGKx/HUU/etbUGTJv91Fs=
github.com/beeper/argo-go v1.1.2/go.mod h1:M+LJAnyowKVQ6Rdj6XYGEn+qcVFkb3R/MUpqkGR0hM4=
github.com/coder/websocket v1.8.14 h1:9L0p0iKiNOibykf283eHkKUHHrpG7f65OE3BhhO7v9g=
github.com/coder/websocket v1.8.14/go.mod h1:NX3SzP+inril6yawo5CQXx8+fk145lPDC6pumgx0mVg=
github.com/coder/websocket v1.8.15 h1:6B2JPeOGlpff2Uz6vOEH1Vzpi0iUz20A+lPVhPHtNUA=
github.com/coder/websocket v1.8.15/go.mod h1:NX3SzP+inril6yawo5CQXx8+fk145lPDC6pumgx0mVg=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/elliotchance/orderedmap/v3 v3.1.0 h1:j4DJ5ObEmMBt/lcwIecKcoRxIQUEnw0L804lXYDt/pg=
@@ -22,37 +22,37 @@ github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHP
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v1.14.42 h1:MigqEP4ZmHw3aIdIT7T+9TLa90Z6smwcthx+Azv4Cgo=
github.com/mattn/go-sqlite3 v1.14.42/go.mod h1:pjEuOr8IwzLJP2MfGeTb0A35jauH+C2kbHKBr7yXKVQ=
github.com/mattn/go-sqlite3 v1.14.45 h1:6KA/spDguL3KV8rnybG7ezSaE4SeMR3KC9VbUoAQaIk=
github.com/mattn/go-sqlite3 v1.14.45/go.mod h1:pjEuOr8IwzLJP2MfGeTb0A35jauH+C2kbHKBr7yXKVQ=
github.com/petermattis/goid v0.0.0-20260330135022-df67b199bc81 h1:WDsQxOJDy0N1VRAjXLpi8sCEZRSGarLWQevDxpTBRrM=
github.com/petermattis/goid v0.0.0-20260330135022-df67b199bc81/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rs/zerolog v1.35.0 h1:VD0ykx7HMiMJytqINBsKcbLS+BJ4WYjz+05us+LRTdI=
github.com/rs/zerolog v1.35.0/go.mod h1:EjML9kdfa/RMA7h/6z6pYmq1ykOuA8/mjWaEvGI+jcw=
github.com/rs/zerolog v1.35.1 h1:m7xQeoiLIiV0BCEY4Hs+j2NG4Gp2o2KPKmhnnLiazKI=
github.com/rs/zerolog v1.35.1/go.mod h1:EjML9kdfa/RMA7h/6z6pYmq1ykOuA8/mjWaEvGI+jcw=
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/vektah/gqlparser/v2 v2.5.27 h1:RHPD3JOplpk5mP5JGX8RKZkt2/Vwj/PZv0HxTdwFp0s=
github.com/vektah/gqlparser/v2 v2.5.27/go.mod h1:D1/VCZtV3LPnQrcPBeR/q5jkSQIPti0uYCP/RI0gIeo=
go.mau.fi/libsignal v0.2.1 h1:vRZG4EzTn70XY6Oh/pVKrQGuMHBkAWlGRC22/85m9L0=
go.mau.fi/libsignal v0.2.1/go.mod h1:iVvjrHyfQqWajOUaMEsIfo3IqgVMrhWcPiiEzk7NgoU=
go.mau.fi/util v0.9.8 h1:+/jf8eM2dAT2wx9UidmaneH28r/CSCKCniCyby1qWz8=
go.mau.fi/util v0.9.8/go.mod h1:up/5mbzH2M1pSBNXqRxODn8dg/hEKbLJu92W4/SNAX0=
golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI=
golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q=
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJkhzJCK5J6kUi1NTVXfM=
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80=
golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA=
golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
go.mau.fi/libsignal v0.2.2 h1:QV+XdzQkm3x3aSG7FcqfGSZuFXz83pRZPBFaPygHbOU=
go.mau.fi/libsignal v0.2.2/go.mod h1:CRlIQg2J8uYTfDFvNoO8/KcZjs5cey0vbc6oj/bssY0=
go.mau.fi/util v0.9.10 h1:wzvz5iDHyqDXB8vgisD4d3SzucLXNM3iNY+1O1RoHtg=
go.mau.fi/util v0.9.10/go.mod h1:YQOxySn+ZE3qSYqNxvyX7Yi3suA8YK17PS6QqBREW7A=
golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto=
golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio=
golang.org/x/exp v0.0.0-20260611194520-c48552f49976 h1:X8Hz2ImujgbmetVuW+w2YkyZChE3cBpZi2P158rTG9M=
golang.org/x/exp v0.0.0-20260611194520-c48552f49976/go.mod h1:vnf4pv9iKZXY58sQE1L86zmNWJ4159e1RkcWiLCkeEY=
golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o=
golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec=
golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM=
golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=
golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw=
golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/text v0.38.0 h1:sXmwo9DwP3OK9EZ7PqAdaooSGozfl/3a6/xJcbzPRhE=
golang.org/x/text v0.38.0/go.mod h1:YXZt3QhHUKYT53r2lLKFIVi6Ao1jdzrTR/KQ09qyxF4=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+27 -14
View File
@@ -60,13 +60,13 @@ func (cli *Client) CreateGroup(ctx context.Context, req ReqCreateGroup) (*types.
Tag: "participant",
Attrs: waBinary.Attrs{"jid": participant},
}
pt, err := cli.Store.PrivacyTokens.GetPrivacyToken(ctx, participant)
token, err := cli.ensureTCToken(ctx, participant)
if err != nil {
return nil, fmt.Errorf("failed to get privacy token for participant %s: %v", participant, err)
} else if pt != nil {
} else if len(token) > 0 {
participantNodes[i].Content = []waBinary.Node{{
Tag: "privacy",
Content: pt.Token,
Content: token,
}}
}
}
@@ -201,6 +201,17 @@ func (cli *Client) UpdateGroupParticipants(ctx context.Context, jid types.JID, p
content[i].Attrs["phone_number"] = pn
}
}
if action == ParticipantChangeAdd {
token, err := cli.ensureTCToken(ctx, participantJID)
if err != nil {
return nil, fmt.Errorf("failed to get privacy token for participant %s: %v", participantJID, err)
} else if len(token) > 0 {
content[i].Content = []waBinary.Node{{
Tag: "privacy",
Content: token,
}}
}
}
}
resp, err := cli.sendGroupIQ(ctx, iqSet, jid, waBinary.Node{
Tag: string(action),
@@ -290,7 +301,7 @@ func (cli *Client) UpdateGroupRequestParticipants(ctx context.Context, jid types
// The avatar should be a JPEG photo, other formats may be rejected with ErrInvalidImageFormat.
// The bytes can be nil to remove the photo. Returns the new picture ID.
func (cli *Client) SetGroupPhoto(ctx context.Context, jid types.JID, avatar []byte) (string, error) {
var content interface{}
var content any
if avatar != nil {
content = []waBinary.Node{{
Tag: "picture",
@@ -455,10 +466,11 @@ func (cli *Client) JoinGroupWithInvite(ctx context.Context, jid, inviter types.J
// GetGroupInfoFromLink resolves the given invite link and asks the WhatsApp servers for info about the group.
// This will not cause the user to join the group.
func (cli *Client) GetGroupInfoFromLink(ctx context.Context, code string) (*types.GroupInfo, error) {
code = strings.TrimPrefix(code, InviteLinkPrefix)
resp, err := cli.sendGroupIQ(ctx, iqGet, types.GroupServerJID, waBinary.Node{
Tag: "invite",
Attrs: waBinary.Attrs{"code": code},
Tag: "invite",
Attrs: waBinary.Attrs{
"code": stripURLPrefix(code, InviteLinkPrefix),
},
})
if errors.Is(err, ErrIQGone) {
return nil, wrapIQError(ErrInviteLinkRevoked, err)
@@ -476,10 +488,11 @@ func (cli *Client) GetGroupInfoFromLink(ctx context.Context, code string) (*type
// JoinGroupWithLink joins the group using the given invite link.
func (cli *Client) JoinGroupWithLink(ctx context.Context, code string) (types.JID, error) {
code = strings.TrimPrefix(code, InviteLinkPrefix)
resp, err := cli.sendGroupIQ(ctx, iqSet, types.GroupServerJID, waBinary.Node{
Tag: "invite",
Attrs: waBinary.Attrs{"code": code},
Tag: "invite",
Attrs: waBinary.Attrs{
"code": stripURLPrefix(code, InviteLinkPrefix),
},
})
if errors.Is(err, ErrIQGone) {
return types.EmptyJID, wrapIQError(ErrInviteLinkRevoked, err)
@@ -521,7 +534,7 @@ func (cli *Client) GetJoinedGroups(ctx context.Context) ([]*types.GroupInfo, err
var allRedactedPhones []store.RedactedPhoneEntry
for _, child := range children {
if child.Tag != "group" {
cli.Log.Debugf("Unexpected child in group list response: %s", child.XMLString())
cli.Log.Debugf("Unexpected child in group list response: %s", &child)
continue
}
parsed, parseErr := cli.parseGroupNode(&child)
@@ -711,7 +724,7 @@ func (cli *Client) parseGroupNode(groupNode *waBinary.Node) (*types.GroupInfo, e
group.NameSetBy = ag.OptionalJIDOrEmpty("s_o")
group.NameSetByPN = ag.OptionalJIDOrEmpty("s_o_pn")
group.GroupCreated = ag.UnixTime("creation")
group.GroupCreated = ag.OptionalUnixTime("creation")
group.CreatorCountryCode = ag.OptionalString("creator_country_code")
group.AnnounceVersionID = ag.OptionalString("a_v_id")
@@ -758,7 +771,7 @@ func (cli *Client) parseGroupNode(groupNode *waBinary.Node) (*types.GroupInfo, e
case "suspended":
group.Suspended = true
default:
cli.Log.Debugf("Unknown element in group node %s: %s", group.JID.String(), child.XMLString())
cli.Log.Debugf("Unknown element in group node %s: %s", group.JID.String(), &child)
}
if !childAG.OK() {
cli.Log.Warnf("Possibly failed to parse %s element in group node: %+v", child.Tag, childAG.Errors)
@@ -888,7 +901,7 @@ func (cli *Client) parseGroupChange(node *waBinary.Node) (*events.GroupInfo, []s
topicChild := child.GetChildByTag("body")
topicBytes, ok := topicChild.Content.([]byte)
if !ok {
return nil, nil, fmt.Errorf("group change description has unexpected body: %s", topicChild.XMLString())
return nil, nil, fmt.Errorf("group change description has unexpected body: %s", &topicChild)
}
topicStr = string(topicBytes)
}
Generated
+104 -36
View File
@@ -199,8 +199,20 @@ func (int *DangerousInternalClient) HandleConnectSuccess(ctx context.Context, no
int.c.handleConnectSuccess(ctx, node)
}
func (int *DangerousInternalClient) DownloadAndDecrypt(ctx context.Context, url string, mediaKey []byte, appInfo MediaType, fileLength int, fileEncSHA256, fileSHA256 []byte) (data []byte, err error) {
return int.c.downloadAndDecrypt(ctx, url, mediaKey, appInfo, fileLength, fileEncSHA256, fileSHA256)
func (int *DangerousInternalClient) GenerateCsToken(ctx context.Context, jid types.JID) []byte {
return int.c.generateCsToken(ctx, jid)
}
func (int *DangerousInternalClient) StoreNCTSalt(ctx context.Context, salt []byte) error {
return int.c.storeNCTSalt(ctx, salt)
}
func (int *DangerousInternalClient) ClearNCTSalt(ctx context.Context) error {
return int.c.clearNCTSalt(ctx)
}
func (int *DangerousInternalClient) DownloadAndDecrypt(ctx context.Context, url string, mediaKey []byte, appInfo MediaType, fileEncSHA256, fileSHA256 []byte) (data []byte, err error) {
return int.c.downloadAndDecrypt(ctx, url, mediaKey, appInfo, fileEncSHA256, fileSHA256)
}
func (int *DangerousInternalClient) DownloadPossiblyEncryptedMediaWithRetries(ctx context.Context, url string, checksum []byte) (file, mac []byte, err error) {
@@ -219,8 +231,8 @@ func (int *DangerousInternalClient) DownloadEncryptedMedia(ctx context.Context,
return int.c.downloadEncryptedMedia(ctx, url, checksum)
}
func (int *DangerousInternalClient) DownloadAndDecryptToFile(ctx context.Context, url string, mediaKey []byte, appInfo MediaType, fileLength int, fileEncSHA256, fileSHA256 []byte, file File) error {
return int.c.downloadAndDecryptToFile(ctx, url, mediaKey, appInfo, fileLength, fileEncSHA256, fileSHA256, file)
func (int *DangerousInternalClient) DownloadAndDecryptToFile(ctx context.Context, url string, mediaKey []byte, appInfo MediaType, fileEncSHA256, fileSHA256 []byte, file File) error {
return int.c.downloadAndDecryptToFile(ctx, url, mediaKey, appInfo, fileEncSHA256, fileSHA256, file)
}
func (int *DangerousInternalClient) DownloadPossiblyEncryptedMediaWithRetriesToFile(ctx context.Context, url string, checksum []byte, file File) (mac []byte, err error) {
@@ -503,6 +515,26 @@ func (int *DangerousInternalClient) SendPairError(ctx context.Context, id string
int.c.sendPairError(ctx, id, code, text)
}
func (int *DangerousInternalClient) HandlePasskeyNotification(ctx context.Context, node *waBinary.Node) {
int.c.handlePasskeyNotification(ctx, node)
}
func (int *DangerousInternalClient) TryHandlePasskeyContinuationNotification(ctx context.Context, node *waBinary.Node) {
int.c.tryHandlePasskeyContinuationNotification(ctx, node)
}
func (int *DangerousInternalClient) HandlePasskeyContinuationNotification(ctx context.Context, node *waBinary.Node) error {
return int.c.handlePasskeyContinuationNotification(ctx, node)
}
func (int *DangerousInternalClient) GetCompanionRef(ctx context.Context) (string, error) {
return int.c.getCompanionRef(ctx)
}
func (int *DangerousInternalClient) GetPasskeyRequestOptions(ctx context.Context) (*types.WebAuthnPublicKey, error) {
return int.c.getPasskeyRequestOptions(ctx)
}
func (int *DangerousInternalClient) GetServerPreKeyCount(ctx context.Context) (int, error) {
return int.c.getServerPreKeyCount(ctx)
}
@@ -563,6 +595,14 @@ func (int *DangerousInternalClient) SendMessageReceipt(ctx context.Context, info
int.c.sendMessageReceipt(ctx, info, node)
}
func (int *DangerousInternalClient) ShouldIncludeReportingToken(message *waE2E.Message) bool {
return int.c.shouldIncludeReportingToken(message)
}
func (int *DangerousInternalClient) GetMessageReportingToken(msgProtobuf []byte, msg *waE2E.Message, senderJID, remoteJID types.JID, messageID types.MessageID) waBinary.Node {
return int.c.getMessageReportingToken(msgProtobuf, msg, senderJID, remoteJID, messageID)
}
func (int *DangerousInternalClient) GenerateRequestID() string {
return int.c.generateRequestID()
}
@@ -643,30 +683,6 @@ func (int *DangerousInternalClient) SendRetryReceipt(ctx context.Context, node *
int.c.sendRetryReceipt(ctx, node, info, forceIncludeIdentity)
}
func (int *DangerousInternalClient) SendGroupV3(ctx context.Context, to, ownID types.JID, id types.MessageID, messageApp []byte, msgAttrs messageAttrs, frankingTag []byte, timings *MessageDebugTimings) (string, []byte, error) {
return int.c.sendGroupV3(ctx, to, ownID, id, messageApp, msgAttrs, frankingTag, timings)
}
func (int *DangerousInternalClient) SendDMV3(ctx context.Context, to, ownID types.JID, id types.MessageID, messageApp []byte, msgAttrs messageAttrs, frankingTag []byte, timings *MessageDebugTimings) ([]byte, string, error) {
return int.c.sendDMV3(ctx, to, ownID, id, messageApp, msgAttrs, frankingTag, timings)
}
func (int *DangerousInternalClient) PrepareMessageNodeV3(ctx context.Context, to, ownID types.JID, id types.MessageID, payload *waMsgTransport.MessageTransport_Payload, skdm *waMsgTransport.MessageTransport_Protocol_Ancillary_SenderKeyDistributionMessage, msgAttrs messageAttrs, frankingTag []byte, participants []types.JID, timings *MessageDebugTimings) (*waBinary.Node, []types.JID, error) {
return int.c.prepareMessageNodeV3(ctx, to, ownID, id, payload, skdm, msgAttrs, frankingTag, participants, timings)
}
func (int *DangerousInternalClient) EncryptMessageForDevicesV3(ctx context.Context, allDevices []types.JID, ownID types.JID, id string, payload *waMsgTransport.MessageTransport_Payload, skdm *waMsgTransport.MessageTransport_Protocol_Ancillary_SenderKeyDistributionMessage, dsm *waMsgTransport.MessageTransport_Protocol_Integral_DeviceSentMessage, encAttrs waBinary.Attrs) ([]waBinary.Node, error) {
return int.c.encryptMessageForDevicesV3(ctx, allDevices, ownID, id, payload, skdm, dsm, encAttrs)
}
func (int *DangerousInternalClient) EncryptMessageForDeviceAndWrapV3(ctx context.Context, payload *waMsgTransport.MessageTransport_Payload, skdm *waMsgTransport.MessageTransport_Protocol_Ancillary_SenderKeyDistributionMessage, dsm *waMsgTransport.MessageTransport_Protocol_Integral_DeviceSentMessage, to types.JID, bundle *prekey.Bundle, encAttrs waBinary.Attrs) (*waBinary.Node, error) {
return int.c.encryptMessageForDeviceAndWrapV3(ctx, payload, skdm, dsm, to, bundle, encAttrs)
}
func (int *DangerousInternalClient) EncryptMessageForDeviceV3(ctx context.Context, payload *waMsgTransport.MessageTransport_Payload, skdm *waMsgTransport.MessageTransport_Protocol_Ancillary_SenderKeyDistributionMessage, dsm *waMsgTransport.MessageTransport_Protocol_Integral_DeviceSentMessage, to types.JID, bundle *prekey.Bundle, extraAttrs waBinary.Attrs) (*waBinary.Node, error) {
return int.c.encryptMessageForDeviceV3(ctx, payload, skdm, dsm, to, bundle, extraAttrs)
}
func (int *DangerousInternalClient) SendNewsletter(ctx context.Context, to types.JID, id types.MessageID, message *waE2E.Message, mediaID string, timings *MessageDebugTimings) ([]byte, error) {
return int.c.sendNewsletter(ctx, to, id, message, mediaID, timings)
}
@@ -711,6 +727,66 @@ func (int *DangerousInternalClient) EncryptMessageForDevice(ctx context.Context,
return int.c.encryptMessageForDevice(ctx, plaintext, to, bundle, extraAttrs, existingSessions)
}
func (int *DangerousInternalClient) SendGroupV3(ctx context.Context, to, ownID types.JID, id types.MessageID, messageApp []byte, msgAttrs messageAttrs, frankingTag []byte, timings *MessageDebugTimings) (string, []byte, error) {
return int.c.sendGroupV3(ctx, to, ownID, id, messageApp, msgAttrs, frankingTag, timings)
}
func (int *DangerousInternalClient) SendDMV3(ctx context.Context, to, ownID types.JID, id types.MessageID, messageApp []byte, msgAttrs messageAttrs, frankingTag []byte, timings *MessageDebugTimings) ([]byte, string, error) {
return int.c.sendDMV3(ctx, to, ownID, id, messageApp, msgAttrs, frankingTag, timings)
}
func (int *DangerousInternalClient) PrepareMessageNodeV3(ctx context.Context, to, ownID types.JID, id types.MessageID, payload *waMsgTransport.MessageTransport_Payload, skdm *waMsgTransport.MessageTransport_Protocol_Ancillary_SenderKeyDistributionMessage, msgAttrs messageAttrs, frankingTag []byte, participants []types.JID, timings *MessageDebugTimings) (*waBinary.Node, []types.JID, error) {
return int.c.prepareMessageNodeV3(ctx, to, ownID, id, payload, skdm, msgAttrs, frankingTag, participants, timings)
}
func (int *DangerousInternalClient) EncryptMessageForDevicesV3(ctx context.Context, allDevices []types.JID, ownID types.JID, id string, payload *waMsgTransport.MessageTransport_Payload, skdm *waMsgTransport.MessageTransport_Protocol_Ancillary_SenderKeyDistributionMessage, dsm *waMsgTransport.MessageTransport_Protocol_Integral_DeviceSentMessage, encAttrs waBinary.Attrs) ([]waBinary.Node, error) {
return int.c.encryptMessageForDevicesV3(ctx, allDevices, ownID, id, payload, skdm, dsm, encAttrs)
}
func (int *DangerousInternalClient) EncryptMessageForDeviceAndWrapV3(ctx context.Context, payload *waMsgTransport.MessageTransport_Payload, skdm *waMsgTransport.MessageTransport_Protocol_Ancillary_SenderKeyDistributionMessage, dsm *waMsgTransport.MessageTransport_Protocol_Integral_DeviceSentMessage, to types.JID, bundle *prekey.Bundle, encAttrs waBinary.Attrs) (*waBinary.Node, error) {
return int.c.encryptMessageForDeviceAndWrapV3(ctx, payload, skdm, dsm, to, bundle, encAttrs)
}
func (int *DangerousInternalClient) EncryptMessageForDeviceV3(ctx context.Context, payload *waMsgTransport.MessageTransport_Payload, skdm *waMsgTransport.MessageTransport_Protocol_Ancillary_SenderKeyDistributionMessage, dsm *waMsgTransport.MessageTransport_Protocol_Integral_DeviceSentMessage, to types.JID, bundle *prekey.Bundle, extraAttrs waBinary.Attrs) (*waBinary.Node, error) {
return int.c.encryptMessageForDeviceV3(ctx, payload, skdm, dsm, to, bundle, extraAttrs)
}
func (int *DangerousInternalClient) ResolveTCTokenStorageLID(ctx context.Context, jid types.JID) types.JID {
return int.c.resolveTCTokenStorageLID(ctx, jid)
}
func (int *DangerousInternalClient) GetTCTokenSenderTS(jid types.JID) time.Time {
return int.c.getTCTokenSenderTS(jid)
}
func (int *DangerousInternalClient) ValidateAndSetTCTokenSenderTS(jid types.JID, storedSenderTimestamp time.Time) bool {
return int.c.validateAndSetTCTokenSenderTS(jid, storedSenderTimestamp)
}
func (int *DangerousInternalClient) SetTCTokenSenderTS(jid types.JID, ts time.Time) {
int.c.setTCTokenSenderTS(jid, ts)
}
func (int *DangerousInternalClient) UnlockedCleanupTCTokenSenderTSMap() {
int.c.unlockedCleanupTCTokenSenderTSMap()
}
func (int *DangerousInternalClient) EnsureTCToken(ctx context.Context, jid types.JID) (token []byte, err error) {
return int.c.ensureTCToken(ctx, jid)
}
func (int *DangerousInternalClient) DeleteExpiredPrivacyTokens() {
int.c.deleteExpiredPrivacyTokens()
}
func (int *DangerousInternalClient) IssuePrivacyTokenAndSave(jid types.JID, senderTimestamp time.Time) {
int.c.issuePrivacyTokenAndSave(jid, senderTimestamp)
}
func (int *DangerousInternalClient) IssuePrivacyToken(ctx context.Context, jid types.JID, timestamp time.Time) (*waBinary.Node, error) {
return int.c.issuePrivacyToken(ctx, jid, timestamp)
}
func (int *DangerousInternalClient) RawUpload(ctx context.Context, dataToUpload io.Reader, uploadSize uint64, fileHash []byte, appInfo MediaType, newsletter bool, resp *UploadResponse) error {
return int.c.rawUpload(ctx, dataToUpload, uploadSize, fileHash, appInfo, newsletter, resp)
}
@@ -746,11 +822,3 @@ func (int *DangerousInternalClient) Usync(ctx context.Context, jids []types.JID,
func (int *DangerousInternalClient) ParseBlocklist(node *waBinary.Node) *types.Blocklist {
return int.c.parseBlocklist(node)
}
func (int *DangerousInternalClient) ShouldIncludeReportingToken(message *waE2E.Message) bool {
return int.c.shouldIncludeReportingToken(message)
}
func (int *DangerousInternalClient) GetMessageReportingToken(msgProtobuf []byte, msg *waE2E.Message, senderJID, remoteJID types.JID, messageID types.MessageID) waBinary.Node {
return int.c.getMessageReportingToken(msgProtobuf, msg, senderJID, remoteJID, messageID)
}
+4 -4
View File
@@ -101,11 +101,11 @@ func main() {
fset := token.NewFileSet()
fileNames := []string{
"appstate.go", "armadillomessage.go", "broadcast.go", "call.go", "client.go",
"connectionevents.go", "download.go", "download-to-file.go", "group.go", "handshake.go",
"connectionevents.go", "cstoken.go", "download.go", "download-to-file.go", "group.go", "handshake.go",
"keepalive.go", "mediaconn.go", "mediaretry.go", "message.go", "msgsecret.go",
"newsletter.go", "notification.go", "pair-code.go", "pair.go", "prekeys.go",
"presence.go", "privacysettings.go", "push.go", "qrchan.go", "receipt.go", "request.go",
"retry.go", "sendfb.go", "send.go", "upload.go", "user.go", "reportingtoken.go",
"newsletter.go", "notification.go", "pair-code.go", "pair.go", "pair-passkey.go", "prekeys.go",
"presence.go", "privacysettings.go", "push.go", "qrchan.go", "receipt.go", "reportingtoken.go",
"request.go", "retry.go", "send.go", "sendfb.go", "tctoken.go", "upload.go", "user.go",
}
files := make([]*ast.File, len(fileNames))
for i, name := range fileNames {
+1 -1
View File
@@ -82,7 +82,7 @@ func (cli *Client) queryMediaConn(ctx context.Context) (*MediaConn, error) {
}
for _, child := range respMC.GetChildren() {
if child.Tag != "host" {
cli.Log.Warnf("Unexpected child in media_conn element: %s", child.XMLString())
cli.Log.Warnf("Unexpected child in media_conn element: %s", &child)
continue
}
cag := child.AttrGetter()
+1 -1
View File
@@ -60,7 +60,7 @@ func encryptMediaRetryReceipt(messageID types.MessageID, mediaKey []byte) (ciphe
// using DecryptMediaRetryNotification and the same media key passed here. If the media retry was successful,
// the decrypted notification should contain an updated DirectPath, which can be used to download the file.
//
// func eventHandler(rawEvt interface{}) {
// func eventHandler(rawEvt any) {
// switch evt := rawEvt.(type) {
// case *events.MediaRetry:
// imageMsg := mediaRetryCache[evt.MessageID]
+37 -24
View File
@@ -44,25 +44,26 @@ func (cli *Client) handleEncryptedMessage(ctx context.Context, node *waBinary.No
info, err := cli.parseMessageInfo(node)
if err != nil {
cli.Log.Warnf("Failed to parse message: %v", err)
cli.sendAck(ctx, node, NackParsingError)
return
}
if !info.SenderAlt.IsEmpty() {
cli.StoreLIDPNMapping(ctx, info.SenderAlt, info.Sender)
} else if !info.RecipientAlt.IsEmpty() {
cli.StoreLIDPNMapping(ctx, info.RecipientAlt, info.Chat)
}
if info.VerifiedName != nil && len(info.VerifiedName.Details.GetVerifiedName()) > 0 {
go cli.updateBusinessName(ctx, info.Sender, info.SenderAlt, info, info.VerifiedName.Details.GetVerifiedName())
}
if len(info.PushName) > 0 && info.PushName != "-" && (cli.MessengerConfig == nil || info.PushName != "username") {
go cli.updatePushName(ctx, info.Sender, info.SenderAlt, info, info.PushName)
}
if info.Sender.Server == types.NewsletterServer {
var cancelled bool
defer cli.maybeDeferredAck(ctx, node)(&cancelled)
cancelled = cli.handlePlaintextMessage(ctx, info, node)
} else {
if !info.SenderAlt.IsEmpty() {
cli.StoreLIDPNMapping(ctx, info.SenderAlt, info.Sender)
} else if !info.RecipientAlt.IsEmpty() {
cli.StoreLIDPNMapping(ctx, info.RecipientAlt, info.Chat)
}
if info.VerifiedName != nil && len(info.VerifiedName.Details.GetVerifiedName()) > 0 {
go cli.updateBusinessName(ctx, info.Sender, info.SenderAlt, info, info.VerifiedName.Details.GetVerifiedName())
}
if len(info.PushName) > 0 && info.PushName != "-" && (cli.MessengerConfig == nil || info.PushName != "username") {
go cli.updatePushName(ctx, info.Sender, info.SenderAlt, info, info.PushName)
}
if info.Sender.Server == types.NewsletterServer {
var cancelled bool
defer cli.maybeDeferredAck(ctx, node)(&cancelled)
cancelled = cli.handlePlaintextMessage(ctx, info, node)
} else {
cli.decryptMessages(ctx, info, node)
}
cli.decryptMessages(ctx, info, node)
}
}
@@ -296,6 +297,12 @@ func (cli *Client) migrateSessionStore(ctx context.Context, pn, lid types.JID) {
}
func (cli *Client) decryptMessages(ctx context.Context, info *types.MessageInfo, node *waBinary.Node) {
defer func() {
if err := recover(); err != nil {
cli.Log.Errorf("Message decryption for %s panicked: %v\n%s", info.ID, err, debug.Stack())
cli.sendAck(ctx, node, 0)
}
}()
unavailableNode, ok := node.GetOptionalChildByTag("unavailable")
if ok && len(node.GetChildrenByTag("enc")) == 0 {
uType := events.UnavailableType(unavailableNode.AttrGetter().String("type"))
@@ -758,14 +765,14 @@ func (cli *Client) DownloadHistorySync(ctx context.Context, notif *waE2E.History
if err := cli.storeNCTSalt(ctx, historySync.GetNctSalt()); err != nil {
cli.Log.Warnf("Failed to store NCT salt from history sync: %v", err)
}
if len(historySync.GetPhoneNumberToLidMappings()) > 0 {
cli.storeHistoricalPNLIDMappings(ctx, historySync.GetPhoneNumberToLidMappings())
}
if historySync.GetSyncType() == waHistorySync.HistorySync_PUSH_NAME {
cli.handleHistoricalPushNames(ctx, historySync.GetPushnames())
} else if len(historySync.GetConversations()) > 0 {
cli.storeHistoricalMessageSecrets(ctx, historySync.GetConversations())
}
if len(historySync.GetPhoneNumberToLidMappings()) > 0 {
cli.storeHistoricalPNLIDMappings(ctx, historySync.GetPhoneNumberToLidMappings())
}
if historySync.GlobalSettings != nil {
cli.storeGlobalSettings(ctx, historySync.GlobalSettings)
}
@@ -938,9 +945,15 @@ func (cli *Client) storeHistoricalMessageSecrets(ctx context.Context, conversati
if chatJID.IsEmpty() {
continue
}
if chatJID.Server == types.DefaultUserServer && conv.GetTcToken() != nil {
var chatPN types.JID
if chatJID.Server == types.DefaultUserServer {
chatPN = chatJID
} else if chatJID.Server == types.HiddenUserServer {
chatPN, _ = cli.Store.LIDs.GetPNForLID(ctx, chatJID)
}
if !chatPN.IsEmpty() && conv.GetTcToken() != nil {
privacyTokens = append(privacyTokens, store.PrivacyToken{
User: chatJID,
User: chatPN,
Token: conv.GetTcToken(),
Timestamp: time.Unix(int64(conv.GetTcTokenTimestamp()), 0),
SenderTimestamp: time.Unix(int64(conv.GetTcTokenSenderTimestamp()), 0),
@@ -952,7 +965,7 @@ func (cli *Client) storeHistoricalMessageSecrets(ctx context.Context, conversati
msgKey := msg.GetMessage().GetKey()
if msgKey.GetFromMe() {
senderJID = ownID
} else if chatJID.Server == types.DefaultUserServer {
} else if chatJID.Server == types.DefaultUserServer || chatJID.Server == types.HiddenUserServer {
senderJID = chatJID
} else if msgKey.GetParticipant() != "" {
senderJID, _ = types.ParseJID(msgKey.GetParticipant())
+16
View File
@@ -13,6 +13,7 @@ import (
"strings"
"time"
"github.com/rs/zerolog"
"go.mau.fi/util/random"
"google.golang.org/protobuf/proto"
@@ -117,10 +118,25 @@ func (cli *Client) decryptMsgSecret(ctx context.Context, msg *events.Message, us
if origSender != storedOrigSender && strings.Contains(err.Error(), "message authentication failed") {
secretKey, additionalData = generateMsgSecretKey(useCase, msg.Info.Sender, origMsgKey.GetID(), storedOrigSender, baseEncKey)
plaintext, err = gcmutil.Decrypt(secretKey, encrypted.GetEncIV(), encrypted.GetEncPayload(), additionalData)
if err == nil {
zerolog.Ctx(ctx).Debug().
Str("orig_message_id", origMsgKey.GetID()).
Str("secret_message_id", msg.Info.ID).
Stringer("stored_orig_sender", storedOrigSender).
Stringer("key_orig_sender", origSender).
Msg("Decrypted message secret with orig sender hack")
}
}
if err != nil {
return nil, fmt.Errorf("failed to decrypt secret message: %w (sender: %s, orig sender: %s and %s)", err, msg.Info.Sender, origSender, storedOrigSender)
}
} else {
zerolog.Ctx(ctx).Debug().
Str("orig_message_id", origMsgKey.GetID()).
Str("secret_message_id", msg.Info.ID).
Stringer("stored_orig_sender", storedOrigSender).
Stringer("key_orig_sender", origSender).
Msg("Decrypted message secret without hack")
}
return plaintext, nil
}
+1 -2
View File
@@ -11,7 +11,6 @@ import (
"encoding/json"
"fmt"
"log"
"strings"
"time"
"github.com/beeper/argo-go/codec"
@@ -278,7 +277,7 @@ func (cli *Client) GetNewsletterInfo(ctx context.Context, jid types.JID) (*types
// Note that the ViewerMeta field of the returned NewsletterMetadata will be nil.
func (cli *Client) GetNewsletterInfoWithInvite(ctx context.Context, key string) (*types.NewsletterMetadata, error) {
return cli.getNewsletterInfo(ctx, map[string]any{
"key": strings.TrimPrefix(key, NewsletterLinkPrefix),
"key": stripURLPrefix(key, NewsletterLinkPrefix),
"type": types.NewsletterKeyTypeInvite,
}, false)
}
+22 -7
View File
@@ -30,15 +30,15 @@ func (cli *Client) handleEncryptNotification(ctx context.Context, node *waBinary
ag := count.AttrGetter()
otksLeft := ag.Int("value")
if !ag.OK() {
cli.Log.Warnf("Didn't get number of OTKs left in encryption notification %s", node.XMLString())
cli.Log.Warnf("Didn't get number of OTKs left in encryption notification %s", node)
return
}
cli.Log.Infof("Got prekey count from server: %s", node.XMLString())
cli.Log.Infof("Got prekey count from server: %s", node)
if otksLeft < MinPreKeyCount {
cli.uploadPreKeys(ctx, false)
}
} else if _, ok := node.GetOptionalChildByTag("identity"); ok {
cli.Log.Debugf("Got identity change for %s: %s, deleting all identities/sessions for that number", from, node.XMLString())
cli.Log.Debugf("Got identity change for %s: %s, deleting all identities/sessions for that number", from, node)
err := cli.Store.Identities.DeleteAllIdentities(ctx, from.User)
if err != nil {
cli.Log.Warnf("Failed to delete all identities of %s from store after identity change: %v", from, err)
@@ -66,7 +66,7 @@ func (cli *Client) handleEncryptNotification(ctx context.Context, node *waBinary
}
cli.dispatchEvent(&events.IdentityChange{JID: from, Timestamp: ts})
} else {
cli.Log.Debugf("Got unknown encryption notification from server: %s", node.XMLString())
cli.Log.Debugf("Got unknown encryption notification from server: %s", node)
}
}
@@ -255,7 +255,7 @@ func (cli *Client) handleBlocklist(ctx context.Context, node *waBinary.Node) {
Action: events.BlocklistChangeAction(ag.String("action")),
}
if !ag.OK() {
cli.Log.Warnf("Unexpected data in blocklist event child %v: %v", child.XMLString(), ag.Error())
cli.Log.Warnf("Unexpected data in blocklist event child %s: %v", &child, ag.Error())
continue
}
evt.Changes = append(evt.Changes, change)
@@ -399,6 +399,7 @@ type newsletterEvent struct {
// _on_admin_metadata_update -> id, thread_metadata, messages
// _on_metadata_update
// _on_state_change -> id, is_requestor, state
NotifyAccountReachoutTimelock *events.NotifyAccountReachoutTimelock `json:"xwa2_notify_account_reachout_timelock"`
}
func (cli *Client) handleMexNotification(ctx context.Context, node *waBinary.Node) {
@@ -406,6 +407,10 @@ func (cli *Client) handleMexNotification(ctx context.Context, node *waBinary.Nod
if child.Tag != "update" {
continue
}
mnd := events.MexNotificationData{
Timestamp: node.AttrGetter().OptionalUnixTime("t"),
OpName: child.AttrGetter().OptionalString("op_name"),
}
childData, ok := child.Content.([]byte)
if !ok {
continue
@@ -417,11 +422,17 @@ func (cli *Client) handleMexNotification(ctx context.Context, node *waBinary.Nod
continue
}
if wrapper.Data.Join != nil {
wrapper.Data.Join.Mex = mnd
cli.dispatchEvent(wrapper.Data.Join)
} else if wrapper.Data.Leave != nil {
wrapper.Data.Leave.Mex = mnd
cli.dispatchEvent(wrapper.Data.Leave)
} else if wrapper.Data.MuteChange != nil {
wrapper.Data.MuteChange.Mex = mnd
cli.dispatchEvent(wrapper.Data.MuteChange)
} else if wrapper.Data.NotifyAccountReachoutTimelock != nil {
wrapper.Data.NotifyAccountReachoutTimelock.Mex = mnd
cli.dispatchEvent(wrapper.Data.NotifyAccountReachoutTimelock)
}
}
}
@@ -446,13 +457,13 @@ func (cli *Client) handleStatusNotification(ctx context.Context, node *waBinary.
}
func (cli *Client) handleNotification(ctx context.Context, node *waBinary.Node) {
var cancelled bool
defer cli.maybeDeferredAck(ctx, node)(&cancelled)
ag := node.AttrGetter()
notifType := ag.String("type")
if !ag.OK() {
return
}
var cancelled bool
defer cli.maybeDeferredAck(ctx, node)(&cancelled)
switch notifType {
case "encrypt":
go cli.handleEncryptNotification(ctx, node)
@@ -493,6 +504,10 @@ func (cli *Client) handleNotification(ctx context.Context, node *waBinary.Node)
cli.handleMexNotification(ctx, node)
case "status":
cli.handleStatusNotification(ctx, node)
case "passkey_prologue_request":
cli.handlePasskeyNotification(ctx, node)
case "crsc_continuation":
go cli.tryHandlePasskeyContinuationNotification(ctx, node)
// Other types: business, disappearing_mode, server, status, pay, psa
default:
cli.Log.Debugf("Unhandled notification with type %s", notifType)
+4 -3
View File
@@ -133,12 +133,12 @@ func (cli *Client) PairPhone(ctx context.Context, phone string, showPushNotifica
if !ok {
return "", fmt.Errorf("unexpected type %T in content of link_code_pairing_ref tag", pairingRefNode.Content)
}
cli.phoneLinkingCache = &phoneLinkingCache{
cli.phoneLinkingCache.Store(&phoneLinkingCache{
jid: jid,
keyPair: ephemeralKeyPair,
linkingCode: encodedLinkingCode,
pairingRef: string(pairingRef),
}
})
return encodedLinkingCode[0:4] + "-" + encodedLinkingCode[4:], nil
}
@@ -157,10 +157,11 @@ func (cli *Client) handleCodePairNotification(ctx context.Context, parentNode *w
In: "notification",
}
}
linkCache := cli.phoneLinkingCache
linkCache := cli.phoneLinkingCache.Load()
if linkCache == nil {
return fmt.Errorf("received code pair notification without a pending pairing")
}
cli.paired.Store(false)
linkCodePairingRef, _ := node.GetChildByTag("link_code_pairing_ref").Content.([]byte)
if string(linkCodePairingRef) != linkCache.pairingRef {
return fmt.Errorf("pairing ref mismatch in code pair notification")
+324
View File
@@ -0,0 +1,324 @@
// Copyright (c) 2026 Tulir Asokan
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package whatsmeow
import (
"context"
"crypto/hmac"
"crypto/sha256"
"encoding/json"
"fmt"
"time"
"go.mau.fi/util/random"
"golang.org/x/crypto/curve25519"
"google.golang.org/protobuf/proto"
waBinary "go.mau.fi/whatsmeow/binary"
"go.mau.fi/whatsmeow/proto/waCompanionReg"
"go.mau.fi/whatsmeow/store"
"go.mau.fi/whatsmeow/types"
"go.mau.fi/whatsmeow/types/events"
"go.mau.fi/whatsmeow/util/gcmutil"
"go.mau.fi/whatsmeow/util/hkdfutil"
"go.mau.fi/whatsmeow/util/keys"
)
type passkeyLinkingCache struct {
keyPair *keys.KeyPair
companionNonce []byte
pairingRef string
deviceType waCompanionReg.DeviceProps_PlatformType
encryptionKey []byte
}
type passkeyHandoffKey struct {
hmac []byte
ts time.Time
}
func (k *passkeyHandoffKey) Valid() bool {
return k != nil && time.Since(k.ts) < 5*time.Minute
}
func (cli *Client) handlePasskeyNotification(ctx context.Context, node *waBinary.Node) {
if fromJID := node.AttrGetter().JID("from"); fromJID != types.ServerJID {
cli.Log.Warnf("Ignoring passkey notification from non-server JID %s", fromJID)
return
}
pubKey, err := parsePasskeyNotification(node)
if err != nil {
cli.Log.Warnf("Failed to parse passkey notification: %v", err)
var secondErr error
pubKey, secondErr = cli.getPasskeyRequestOptions(ctx)
if secondErr != nil {
cli.Log.Warnf("Failed to fetch passkey options: %v", secondErr)
cli.dispatchEvent(&events.PairPasskeyError{
Error: fmt.Errorf("failed to parse passkey notification: %w (fetching key also failed: %w)", err, secondErr),
Continuation: false,
})
return
}
cli.Log.Debugf("Successfully fetched passkey options after failing to parse notification")
}
cli.passkeyHandoffKey.Store(&passkeyHandoffKey{
hmac: hkdfutil.SHA256(cli.Store.AdvSecretKey, nil, []byte("shortcake-passkey-handoff-v1"), 32),
ts: time.Now(),
})
cli.Store.AdvSecretKey = random.Bytes(32)
cli.dispatchEvent(&events.PairPasskeyRequest{PublicKey: pubKey})
}
// SendPasskeyResponse sends a WebAuthn response from the authenticator to the server.
// This should be called after receiving an [*events.PairPasskeyRequest] and asking the authenticator for a response.
func (cli *Client) SendPasskeyResponse(ctx context.Context, passkeyResp *types.WebAuthnResponse) error {
marshaledResp, err := json.Marshal(passkeyResp)
if err != nil {
return fmt.Errorf("failed to marshal WebAuthnResponse: %w", err)
}
companionRef, err := cli.getCompanionRef(ctx)
if err != nil {
return fmt.Errorf("failed to get companion ref: %w", err)
}
companionEphemeralKeyPair := keys.NewKeyPair()
companionNonce := random.Bytes(32)
deviceType := store.DeviceProps.GetPlatformType()
ident, err := proto.Marshal(&waCompanionReg.CompanionEphemeralIdentity{
PublicKey: companionEphemeralKeyPair.Pub[:],
DeviceType: &deviceType,
Ref: &companionRef,
})
if err != nil {
return fmt.Errorf("failed to marshal CompanionEphemeralIdentity: %w", err)
}
commitment := sha256.Sum256(append(ident, companionNonce...))
prologuePayload, err := proto.Marshal(&waCompanionReg.ProloguePayload{
CompanionEphemeralIdentity: ident,
Commitment: &waCompanionReg.CompanionCommitment{
Hash: commitment[:],
},
})
if err != nil {
return fmt.Errorf("failed to marshal ProloguePayload: %w", err)
}
cli.passkeyLinkingCache.Store(&passkeyLinkingCache{
keyPair: companionEphemeralKeyPair,
companionNonce: companionNonce,
pairingRef: companionRef,
deviceType: deviceType,
})
prologueContent := []waBinary.Node{
{Tag: "credential_id", Content: []byte(passkeyResp.RawID)},
{Tag: "webauthn_assertion", Content: marshaledResp},
{Tag: "prologue_payload", Content: prologuePayload},
}
if handoffKey := cli.passkeyHandoffKey.Load(); handoffKey.Valid() {
h := hmac.New(sha256.New, handoffKey.hmac)
h.Write(prologuePayload)
pairingHandoffProof := h.Sum(nil)
prologueContent = append(prologueContent, waBinary.Node{
Tag: "pairing_handoff_proof",
Content: pairingHandoffProof,
})
cli.passkeySkipHandoffUX.Store(true)
} else {
cli.passkeySkipHandoffUX.Store(false)
}
_, err = cli.sendIQ(ctx, infoQuery{
Namespace: "md",
Type: iqSet,
To: types.ServerJID,
Content: []waBinary.Node{{
Tag: "passkey_prologue",
Content: prologueContent,
}},
})
if err != nil {
return fmt.Errorf("failed to send passkey response: %w", err)
}
cli.passkeyHandoffKey.Store(nil)
return nil
}
func (cli *Client) tryHandlePasskeyContinuationNotification(ctx context.Context, node *waBinary.Node) {
if fromJID := node.AttrGetter().JID("from"); fromJID != types.ServerJID {
cli.Log.Warnf("Ignoring passkey continuation notification from non-server JID %s", fromJID)
return
}
err := cli.handlePasskeyContinuationNotification(ctx, node)
if err != nil {
cli.Log.Warnf("Failed to handle passkey continuation notification: %v", err)
cli.dispatchEvent(&events.PairPasskeyError{
Error: err,
Continuation: true,
})
}
}
func (cli *Client) handlePasskeyContinuationNotification(ctx context.Context, node *waBinary.Node) error {
cache := cli.passkeyLinkingCache.Load()
if cache == nil {
return fmt.Errorf("received passkey continuation notification without a linking cache")
}
primaryEphemeralIdentity, err := parsePasskeyContinuationNotification(node)
if err != nil {
return fmt.Errorf("failed to parse passkey continuation notification: %w", err)
}
sharedSecret, err := curve25519.X25519(cache.keyPair.Priv[:], primaryEphemeralIdentity.PublicKey)
if err != nil {
return fmt.Errorf("failed to compute shared secret: %w", err)
}
_, err = cli.sendIQ(ctx, infoQuery{
Namespace: "md",
Type: iqSet,
To: types.ServerJID,
Content: []waBinary.Node{{
Tag: "companion_nonce",
Content: cache.companionNonce,
}},
})
if err != nil {
return fmt.Errorf("failed to send companion nonce: %w", err)
}
const info = "Pairing Information Encryption Key"
salt := fmt.Sprintf("Companion Pairing %d with ref %s", cache.deviceType, cache.pairingRef)
cache.encryptionKey = hkdfutil.SHA256(sharedSecret, []byte(salt), []byte(info), 32)
digest := sha256.Sum256(append(cache.companionNonce, primaryEphemeralIdentity.PublicKey...))
codeBytes := make([]byte, 5)
for i := range codeBytes {
codeBytes[i] = primaryEphemeralIdentity.Nonce[i] ^ digest[i]
}
encodedCode := linkingBase32.EncodeToString(codeBytes)
cli.dispatchEvent(&events.PairPasskeyConfirmation{
Code: encodedCode[0:4] + "-" + encodedCode[4:],
SkipHandoffUX: cli.passkeySkipHandoffUX.Load(),
})
return nil
}
// SendPasskeyConfirmation sends a confirmation to the server that the pairing code in [*events.PairPasskeyConfirmation]
// was shown to the user and they confirmed it. If the event has the SkipHandoffUX flag, showing the code to the user
// can be skipped.
func (cli *Client) SendPasskeyConfirmation(ctx context.Context) error {
cache := cli.passkeyLinkingCache.Load()
if cache == nil {
return fmt.Errorf("no passkey linking cache available")
} else if cache.encryptionKey == nil {
return fmt.Errorf("passkey linking cache does not have an encryption key yet")
}
req, err := proto.Marshal(&waCompanionReg.PairingRequest{
CompanionPublicKey: cli.Store.NoiseKey.Pub[:],
CompanionIdentityKey: cli.Store.IdentityKey.Pub[:],
AdvSecret: cli.Store.AdvSecretKey,
})
if err != nil {
return fmt.Errorf("failed to marshal PairingRequest: %w", err)
}
iv := random.Bytes(12)
encryptedReq, err := gcmutil.Encrypt(cache.encryptionKey, iv, req, nil)
if err != nil {
return fmt.Errorf("failed to encrypt PairingRequest: %w", err)
}
wrappedReq, err := proto.Marshal(&waCompanionReg.EncryptedPairingRequest{
EncryptedPayload: encryptedReq,
IV: iv,
})
if err != nil {
return fmt.Errorf("failed to marshal EncryptedPairingRequest: %w", err)
}
_, err = cli.sendIQ(ctx, infoQuery{
Namespace: "md",
Type: iqSet,
To: types.ServerJID,
Content: []waBinary.Node{{
Tag: "encrypted_pairing_request",
Content: wrappedReq,
}},
})
if err != nil {
return err
}
cli.passkeyLinkingCache.Store(nil)
return nil
}
func (cli *Client) getCompanionRef(ctx context.Context) (string, error) {
resp, err := cli.sendIQ(ctx, infoQuery{
Namespace: "md",
Type: iqGet,
To: types.ServerJID,
Content: []waBinary.Node{{Tag: "ref"}},
})
if err != nil {
return "", err
}
ref, ok := resp.GetOptionalChildByTag("ref")
if !ok {
return "", &ElementMissingError{Tag: "ref", In: "get ref response"}
}
contentBytes, ok := ref.Content.([]byte)
if !ok {
return "", fmt.Errorf("unexpected content type %T for <ref> node", ref.Content)
}
return string(contentBytes), nil
}
func (cli *Client) getPasskeyRequestOptions(ctx context.Context) (*types.WebAuthnPublicKey, error) {
resp, err := cli.sendIQ(ctx, infoQuery{
Namespace: "md",
Type: iqGet,
To: types.ServerJID,
Content: []waBinary.Node{{Tag: "passkey_request_options"}},
})
if err != nil {
return nil, err
}
return parsePasskeyNotification(resp)
}
func parsePasskeyNotification(node *waBinary.Node) (*types.WebAuthnPublicKey, error) {
opts, ok := node.GetOptionalChildByTag("passkey_request_options")
if !ok {
return nil, &ElementMissingError{Tag: "passkey_request_options", In: "passkey notification"}
}
content, ok := opts.Content.([]byte)
if !ok {
return nil, fmt.Errorf("unexpected content type %T for <passkey_request_options> node", opts.Content)
}
var pubKey types.WebAuthnPublicKey
err := json.Unmarshal(content, &pubKey)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal <passkey_request_options> content: %w", err)
}
return &pubKey, nil
}
func parsePasskeyContinuationNotification(node *waBinary.Node) (*waCompanionReg.PrimaryEphemeralIdentity, error) {
opts, ok := node.GetOptionalChildByTag("primary_ephemeral_identity")
if !ok {
return nil, &ElementMissingError{Tag: "primary_ephemeral_identity", In: "passkey continuation notification"}
}
content, ok := opts.Content.([]byte)
if !ok {
return nil, fmt.Errorf("unexpected content type %T for <primary_ephemeral_identity> node", opts.Content)
}
var buf waCompanionReg.PrimaryEphemeralIdentity
err := proto.Unmarshal(content, &buf)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal primary ephemeral identity: %w", err)
} else if len(buf.PublicKey) != 32 {
return nil, fmt.Errorf("unexpected public key length %d primary ephemeral identity", len(buf.PublicKey))
} else if len(buf.Nonce) != 32 {
return nil, fmt.Errorf("unexpected nonce length %d primary ephemeral identity", len(buf.Nonce))
}
return &buf, err
}
+10 -3
View File
@@ -49,6 +49,7 @@ func (cli *Client) handleIQ(ctx context.Context, node *waBinary.Node) {
}
func (cli *Client) handlePairDevice(ctx context.Context, node *waBinary.Node) {
cli.paired.Store(false)
pairDevice := node.GetChildByTag("pair-device")
err := cli.sendNode(ctx, waBinary.Node{
Tag: "iq",
@@ -119,6 +120,7 @@ func (cli *Client) makeQRData(ref []byte, clientType PairClientType) string {
}
func (cli *Client) handlePairSuccess(ctx context.Context, node *waBinary.Node) {
cli.serverTimeOffset.Store(int64(node.AttrGetter().UnixTime("t").Sub(time.Now().Round(time.Second))))
id := node.Attrs["id"].(string)
pairSuccess := node.GetChildByTag("pair-success")
@@ -127,18 +129,22 @@ func (cli *Client) handlePairSuccess(ctx context.Context, node *waBinary.Node) {
jid, _ := pairSuccess.GetChildByTag("device").Attrs["jid"].(types.JID)
lid, _ := pairSuccess.GetChildByTag("device").Attrs["lid"].(types.JID)
platform, _ := pairSuccess.GetChildByTag("platform").Attrs["name"].(string)
cli.serverTimeOffset.Store(int64(node.AttrGetter().UnixTime("t").Sub(time.Now().Round(time.Second))))
clientPropsBytes, _ := pairSuccess.GetChildByTag("client-props").Content.([]byte)
var props waCompanionReg.ClientPairingProps
if err := proto.Unmarshal(clientPropsBytes, &props); err != nil {
cli.Log.Warnf("Failed to parse client pairing props: %v", err)
}
go func() {
err := cli.handlePair(ctx, deviceIdentityBytes, id, businessName, platform, jid, lid)
if err != nil {
cli.Log.Errorf("Failed to pair device: %v", err)
cli.Disconnect()
cli.dispatchEvent(&events.PairError{ID: jid, LID: lid, BusinessName: businessName, Platform: platform, Error: err})
cli.dispatchEvent(&events.PairError{ID: jid, LID: lid, BusinessName: businessName, Platform: platform, Props: &props, Error: err})
} else {
cli.Log.Infof("Successfully paired %s", cli.Store.ID)
go cli.sendUnifiedSession()
cli.dispatchEvent(&events.PairSuccess{ID: jid, LID: lid, BusinessName: businessName, Platform: platform})
cli.dispatchEvent(&events.PairSuccess{ID: jid, LID: lid, BusinessName: businessName, Platform: platform, Props: &props})
}
}()
}
@@ -222,6 +228,7 @@ func (cli *Client) handlePair(ctx context.Context, deviceIdentityBytes []byte, r
// Expect a disconnect after this and don't dispatch the usual Disconnected event
cli.expectDisconnect()
cli.paired.Store(true)
err = cli.sendNode(ctx, waBinary.Node{
Tag: "iq",
+1 -1
View File
@@ -180,7 +180,7 @@ func preKeyToNode(key *keys.PreKey) waBinary.Node {
func nodeToPreKeyBundle(deviceID uint32, node waBinary.Node) (*prekey.Bundle, error) {
errorNode, ok := node.GetOptionalChildByTag("error")
if ok && errorNode.Tag == "error" {
return nil, fmt.Errorf("got error getting prekeys: %s", errorNode.XMLString())
return nil, fmt.Errorf("got error getting prekeys: %s", &errorNode)
}
registrationBytes, ok := node.GetChildByTag("registration").Content.([]byte)
+2 -2
View File
@@ -98,7 +98,7 @@ func (cli *Client) SubscribePresence(ctx context.Context, jid types.JID) error {
if cli == nil {
return ErrClientIsNil
}
privacyToken, err := cli.Store.PrivacyTokens.GetPrivacyToken(ctx, jid)
privacyToken, err := cli.ensureTCToken(ctx, jid)
if err != nil {
return fmt.Errorf("failed to get privacy token: %w", err)
} else if privacyToken == nil {
@@ -118,7 +118,7 @@ func (cli *Client) SubscribePresence(ctx context.Context, jid types.JID) error {
if privacyToken != nil {
req.Content = []waBinary.Node{{
Tag: "tctoken",
Content: privacyToken.Token,
Content: privacyToken,
}}
}
return cli.sendNode(ctx, req)
+1
View File
@@ -4,3 +4,4 @@ EBWasm
KTWasm
VestaWasm
waArmadilloLocallyTransformedMessage
MDCoreSyncProtobuf
File diff suppressed because it is too large. Load diff
@@ -127,6 +127,7 @@ message BotSignatureVerificationUseCaseProof {
UNSPECIFIED = 0;
WA_BOT_MSG = 1;
WA_TEE_BOT_MSG = 2;
P2P_PILLS = 3;
}
optional int32 version = 1;
@@ -323,6 +324,11 @@ message BotCapabilityMetadata {
AI_TAB_FORCE_CLIPPY = 59;
UNIFIED_RESPONSE_EMBEDDED_SCREENS = 60;
AI_SUBSCRIPTION_ENABLED = 61;
UNIFIED_RESPONSE_AI_CONTENT_SEARCH_ENABLED = 62;
UNIFIED_RESPONSE_MARKDOWN_LINKS_ENABLED = 63;
AI_RICH_RESPONSE_MAPS_V2_ENABLED = 64;
AI_SUBSCRIPTION_METERING_ENABLED = 65;
RICH_RESPONSE_SPORTS_WIDGET_ENABLED = 66;
}
repeated BotCapabilityType capabilities = 1;
@@ -704,6 +710,16 @@ message AIMediaCollectionMessage {
optional bool hasGlobalCaption = 3;
}
message HatchMetadataSync {
optional bytes data = 1;
optional int64 timestampMS = 2;
optional string requestID = 3;
}
message AIMetadataOperation {
optional HatchMetadataSync hatchMetadataSync = 1;
}
message BotCommandMetadata {
optional string commandName = 1;
optional string commandDescription = 2;
@@ -715,6 +731,10 @@ message BotResolvedToolCallMetadata {
optional string resolutionDataSerialized = 2;
}
message BotPttPromptMetadata {
optional string transcript = 1;
}
message BotMetadata {
optional string personaID = 2;
optional BotPluginMetadata pluginMetadata = 3;
@@ -756,6 +776,8 @@ message BotMetadata {
optional BotCommandMetadata commandMetadata = 39;
optional BotResolvedToolCallMetadata resolvedToolCallMetadata = 40;
optional AISubscriptionUpsellMetadata subscriptionUpsellMetadata = 41;
optional BotPttPromptMetadata pttPromptMetadata = 42;
optional BotHistoryShareMetadata botHistoryShareMetadata = 43;
optional bytes internalMetadata = 999;
}
@@ -767,6 +789,10 @@ message BotGroupMetadata {
repeated BotGroupParticipantMetadata participantsMetadata = 1;
}
message BotHistoryShareMetadata {
repeated BotGroupParticipantMetadata participantsMetadata = 1;
}
message BotRenderingConfigMetadata {
optional string bloksVersioningID = 1;
optional double pixelDensity = 2;
@@ -808,4 +834,15 @@ message BotAgentMetadata {
message BotAgentDeepLinkMetadata {
optional string token = 1;
optional bytes clientPublicKey = 2;
}
message AIProvenance {
message Metadata {
optional bool createdWithGenAi = 1;
optional bool editedWithGenAi = 2;
}
optional Metadata c2PaMetadata = 1;
optional Metadata iptcMetadata = 2;
}
+190
View File
@@ -0,0 +1,190 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
// protoc v7.34.1
// source: waAea/WAWebProtobufsAea.proto
package waAea
import (
reflect "reflect"
sync "sync"
unsafe "unsafe"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type NonE2EEAttestation_AccountType int32
const (
NonE2EEAttestation_E2EE NonE2EEAttestation_AccountType = 0
NonE2EEAttestation_HYBRID_E2EE NonE2EEAttestation_AccountType = 1
NonE2EEAttestation_NON_E2EE NonE2EEAttestation_AccountType = 2
)
// Enum value maps for NonE2EEAttestation_AccountType.
var (
NonE2EEAttestation_AccountType_name = map[int32]string{
0: "E2EE",
1: "HYBRID_E2EE",
2: "NON_E2EE",
}
NonE2EEAttestation_AccountType_value = map[string]int32{
"E2EE": 0,
"HYBRID_E2EE": 1,
"NON_E2EE": 2,
}
)
func (x NonE2EEAttestation_AccountType) Enum() *NonE2EEAttestation_AccountType {
p := new(NonE2EEAttestation_AccountType)
*p = x
return p
}
func (x NonE2EEAttestation_AccountType) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (NonE2EEAttestation_AccountType) Descriptor() protoreflect.EnumDescriptor {
return file_waAea_WAWebProtobufsAea_proto_enumTypes[0].Descriptor()
}
func (NonE2EEAttestation_AccountType) Type() protoreflect.EnumType {
return &file_waAea_WAWebProtobufsAea_proto_enumTypes[0]
}
func (x NonE2EEAttestation_AccountType) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Do not use.
func (x *NonE2EEAttestation_AccountType) UnmarshalJSON(b []byte) error {
num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
if err != nil {
return err
}
*x = NonE2EEAttestation_AccountType(num)
return nil
}
// Deprecated: Use NonE2EEAttestation_AccountType.Descriptor instead.
func (NonE2EEAttestation_AccountType) EnumDescriptor() ([]byte, []int) {
return file_waAea_WAWebProtobufsAea_proto_rawDescGZIP(), []int{0, 0}
}
type NonE2EEAttestation struct {
state protoimpl.MessageState `protogen:"open.v1"`
AccountType *NonE2EEAttestation_AccountType `protobuf:"varint,1,opt,name=accountType,enum=WAWebProtobufsAea.NonE2EEAttestation_AccountType" json:"accountType,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *NonE2EEAttestation) Reset() {
*x = NonE2EEAttestation{}
mi := &file_waAea_WAWebProtobufsAea_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *NonE2EEAttestation) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*NonE2EEAttestation) ProtoMessage() {}
func (x *NonE2EEAttestation) ProtoReflect() protoreflect.Message {
mi := &file_waAea_WAWebProtobufsAea_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use NonE2EEAttestation.ProtoReflect.Descriptor instead.
func (*NonE2EEAttestation) Descriptor() ([]byte, []int) {
return file_waAea_WAWebProtobufsAea_proto_rawDescGZIP(), []int{0}
}
func (x *NonE2EEAttestation) GetAccountType() NonE2EEAttestation_AccountType {
if x != nil && x.AccountType != nil {
return *x.AccountType
}
return NonE2EEAttestation_E2EE
}
var File_waAea_WAWebProtobufsAea_proto protoreflect.FileDescriptor
const file_waAea_WAWebProtobufsAea_proto_rawDesc = "" +
"\n" +
"\x1dwaAea/WAWebProtobufsAea.proto\x12\x11WAWebProtobufsAea\"\xa1\x01\n" +
"\x12NonE2EEAttestation\x12S\n" +
"\vaccountType\x18\x01 \x01(\x0e21.WAWebProtobufsAea.NonE2EEAttestation.AccountTypeR\vaccountType\"6\n" +
"\vAccountType\x12\b\n" +
"\x04E2EE\x10\x00\x12\x0f\n" +
"\vHYBRID_E2EE\x10\x01\x12\f\n" +
"\bNON_E2EE\x10\x02B!Z\x1fgo.mau.fi/whatsmeow/proto/waAea"
var (
file_waAea_WAWebProtobufsAea_proto_rawDescOnce sync.Once
file_waAea_WAWebProtobufsAea_proto_rawDescData []byte
)
func file_waAea_WAWebProtobufsAea_proto_rawDescGZIP() []byte {
file_waAea_WAWebProtobufsAea_proto_rawDescOnce.Do(func() {
file_waAea_WAWebProtobufsAea_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_waAea_WAWebProtobufsAea_proto_rawDesc), len(file_waAea_WAWebProtobufsAea_proto_rawDesc)))
})
return file_waAea_WAWebProtobufsAea_proto_rawDescData
}
var file_waAea_WAWebProtobufsAea_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_waAea_WAWebProtobufsAea_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_waAea_WAWebProtobufsAea_proto_goTypes = []any{
(NonE2EEAttestation_AccountType)(0), // 0: WAWebProtobufsAea.NonE2EEAttestation.AccountType
(*NonE2EEAttestation)(nil), // 1: WAWebProtobufsAea.NonE2EEAttestation
}
var file_waAea_WAWebProtobufsAea_proto_depIdxs = []int32{
0, // 0: WAWebProtobufsAea.NonE2EEAttestation.accountType:type_name -> WAWebProtobufsAea.NonE2EEAttestation.AccountType
1, // [1:1] is the sub-list for method output_type
1, // [1:1] is the sub-list for method input_type
1, // [1:1] is the sub-list for extension type_name
1, // [1:1] is the sub-list for extension extendee
0, // [0:1] is the sub-list for field type_name
}
func init() { file_waAea_WAWebProtobufsAea_proto_init() }
func file_waAea_WAWebProtobufsAea_proto_init() {
if File_waAea_WAWebProtobufsAea_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_waAea_WAWebProtobufsAea_proto_rawDesc), len(file_waAea_WAWebProtobufsAea_proto_rawDesc)),
NumEnums: 1,
NumMessages: 1,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_waAea_WAWebProtobufsAea_proto_goTypes,
DependencyIndexes: file_waAea_WAWebProtobufsAea_proto_depIdxs,
EnumInfos: file_waAea_WAWebProtobufsAea_proto_enumTypes,
MessageInfos: file_waAea_WAWebProtobufsAea_proto_msgTypes,
}.Build()
File_waAea_WAWebProtobufsAea_proto = out.File
file_waAea_WAWebProtobufsAea_proto_goTypes = nil
file_waAea_WAWebProtobufsAea_proto_depIdxs = nil
}
+13
View File
@@ -0,0 +1,13 @@
syntax = "proto2";
package WAWebProtobufsAea;
option go_package = "go.mau.fi/whatsmeow/proto/waAea";
message NonE2EEAttestation {
enum AccountType {
E2EE = 0;
HYBRID_E2EE = 1;
NON_E2EE = 2;
}
optional AccountType accountType = 1;
}
@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
// protoc v6.33.5
// protoc v7.34.1
// source: waDeviceCapabilities/WAWebProtobufsDeviceCapabilities.proto
package waDeviceCapabilities
@@ -207,6 +207,7 @@ type DeviceCapabilities struct {
UserHasAvatar *DeviceCapabilities_UserHasAvatar `protobuf:"bytes,4,opt,name=userHasAvatar" json:"userHasAvatar,omitempty"`
MemberNameTagPrimarySupport *DeviceCapabilities_MemberNameTagPrimarySupport `protobuf:"varint,5,opt,name=memberNameTagPrimarySupport,enum=WAWebProtobufsDeviceCapabilities.DeviceCapabilities_MemberNameTagPrimarySupport" json:"memberNameTagPrimarySupport,omitempty"`
AiThread *DeviceCapabilities_AiThread `protobuf:"bytes,6,opt,name=aiThread" json:"aiThread,omitempty"`
AiFbidMigration *DeviceCapabilities_AiFbidMigration `protobuf:"bytes,7,opt,name=aiFbidMigration" json:"aiFbidMigration,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
@@ -283,6 +284,13 @@ func (x *DeviceCapabilities) GetAiThread() *DeviceCapabilities_AiThread {
return nil
}
func (x *DeviceCapabilities) GetAiFbidMigration() *DeviceCapabilities_AiFbidMigration {
if x != nil {
return x.AiFbidMigration
}
return nil
}
type DeviceCapabilities_AiThread struct {
state protoimpl.MessageState `protogen:"open.v1"`
SupportLevel *DeviceCapabilities_AiThread_SupportLevel `protobuf:"varint,1,opt,name=supportLevel,enum=WAWebProtobufsDeviceCapabilities.DeviceCapabilities_AiThread_SupportLevel" json:"supportLevel,omitempty"`
@@ -327,6 +335,50 @@ func (x *DeviceCapabilities_AiThread) GetSupportLevel() DeviceCapabilities_AiThr
return DeviceCapabilities_AiThread_NONE
}
type DeviceCapabilities_AiFbidMigration struct {
state protoimpl.MessageState `protogen:"open.v1"`
ChatDbMigrationTimestamp *uint64 `protobuf:"varint,1,opt,name=chatDbMigrationTimestamp" json:"chatDbMigrationTimestamp,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *DeviceCapabilities_AiFbidMigration) Reset() {
*x = DeviceCapabilities_AiFbidMigration{}
mi := &file_waDeviceCapabilities_WAWebProtobufsDeviceCapabilities_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *DeviceCapabilities_AiFbidMigration) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DeviceCapabilities_AiFbidMigration) ProtoMessage() {}
func (x *DeviceCapabilities_AiFbidMigration) ProtoReflect() protoreflect.Message {
mi := &file_waDeviceCapabilities_WAWebProtobufsDeviceCapabilities_proto_msgTypes[2]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DeviceCapabilities_AiFbidMigration.ProtoReflect.Descriptor instead.
func (*DeviceCapabilities_AiFbidMigration) Descriptor() ([]byte, []int) {
return file_waDeviceCapabilities_WAWebProtobufsDeviceCapabilities_proto_rawDescGZIP(), []int{0, 1}
}
func (x *DeviceCapabilities_AiFbidMigration) GetChatDbMigrationTimestamp() uint64 {
if x != nil && x.ChatDbMigrationTimestamp != nil {
return *x.ChatDbMigrationTimestamp
}
return 0
}
type DeviceCapabilities_UserHasAvatar struct {
state protoimpl.MessageState `protogen:"open.v1"`
UserHasAvatar *bool `protobuf:"varint,1,opt,name=userHasAvatar" json:"userHasAvatar,omitempty"`
@@ -336,7 +388,7 @@ type DeviceCapabilities_UserHasAvatar struct {
func (x *DeviceCapabilities_UserHasAvatar) Reset() {
*x = DeviceCapabilities_UserHasAvatar{}
mi := &file_waDeviceCapabilities_WAWebProtobufsDeviceCapabilities_proto_msgTypes[2]
mi := &file_waDeviceCapabilities_WAWebProtobufsDeviceCapabilities_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -348,7 +400,7 @@ func (x *DeviceCapabilities_UserHasAvatar) String() string {
func (*DeviceCapabilities_UserHasAvatar) ProtoMessage() {}
func (x *DeviceCapabilities_UserHasAvatar) ProtoReflect() protoreflect.Message {
mi := &file_waDeviceCapabilities_WAWebProtobufsDeviceCapabilities_proto_msgTypes[2]
mi := &file_waDeviceCapabilities_WAWebProtobufsDeviceCapabilities_proto_msgTypes[3]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -361,7 +413,7 @@ func (x *DeviceCapabilities_UserHasAvatar) ProtoReflect() protoreflect.Message {
// Deprecated: Use DeviceCapabilities_UserHasAvatar.ProtoReflect.Descriptor instead.
func (*DeviceCapabilities_UserHasAvatar) Descriptor() ([]byte, []int) {
return file_waDeviceCapabilities_WAWebProtobufsDeviceCapabilities_proto_rawDescGZIP(), []int{0, 1}
return file_waDeviceCapabilities_WAWebProtobufsDeviceCapabilities_proto_rawDescGZIP(), []int{0, 2}
}
func (x *DeviceCapabilities_UserHasAvatar) GetUserHasAvatar() bool {
@@ -384,7 +436,7 @@ type DeviceCapabilities_BusinessBroadcast struct {
func (x *DeviceCapabilities_BusinessBroadcast) Reset() {
*x = DeviceCapabilities_BusinessBroadcast{}
mi := &file_waDeviceCapabilities_WAWebProtobufsDeviceCapabilities_proto_msgTypes[3]
mi := &file_waDeviceCapabilities_WAWebProtobufsDeviceCapabilities_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -396,7 +448,7 @@ func (x *DeviceCapabilities_BusinessBroadcast) String() string {
func (*DeviceCapabilities_BusinessBroadcast) ProtoMessage() {}
func (x *DeviceCapabilities_BusinessBroadcast) ProtoReflect() protoreflect.Message {
mi := &file_waDeviceCapabilities_WAWebProtobufsDeviceCapabilities_proto_msgTypes[3]
mi := &file_waDeviceCapabilities_WAWebProtobufsDeviceCapabilities_proto_msgTypes[4]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -409,7 +461,7 @@ func (x *DeviceCapabilities_BusinessBroadcast) ProtoReflect() protoreflect.Messa
// Deprecated: Use DeviceCapabilities_BusinessBroadcast.ProtoReflect.Descriptor instead.
func (*DeviceCapabilities_BusinessBroadcast) Descriptor() ([]byte, []int) {
return file_waDeviceCapabilities_WAWebProtobufsDeviceCapabilities_proto_rawDescGZIP(), []int{0, 2}
return file_waDeviceCapabilities_WAWebProtobufsDeviceCapabilities_proto_rawDescGZIP(), []int{0, 3}
}
func (x *DeviceCapabilities_BusinessBroadcast) GetImportListEnabled() bool {
@@ -456,7 +508,7 @@ type DeviceCapabilities_LIDMigration struct {
func (x *DeviceCapabilities_LIDMigration) Reset() {
*x = DeviceCapabilities_LIDMigration{}
mi := &file_waDeviceCapabilities_WAWebProtobufsDeviceCapabilities_proto_msgTypes[4]
mi := &file_waDeviceCapabilities_WAWebProtobufsDeviceCapabilities_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -468,7 +520,7 @@ func (x *DeviceCapabilities_LIDMigration) String() string {
func (*DeviceCapabilities_LIDMigration) ProtoMessage() {}
func (x *DeviceCapabilities_LIDMigration) ProtoReflect() protoreflect.Message {
mi := &file_waDeviceCapabilities_WAWebProtobufsDeviceCapabilities_proto_msgTypes[4]
mi := &file_waDeviceCapabilities_WAWebProtobufsDeviceCapabilities_proto_msgTypes[5]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -481,7 +533,7 @@ func (x *DeviceCapabilities_LIDMigration) ProtoReflect() protoreflect.Message {
// Deprecated: Use DeviceCapabilities_LIDMigration.ProtoReflect.Descriptor instead.
func (*DeviceCapabilities_LIDMigration) Descriptor() ([]byte, []int) {
return file_waDeviceCapabilities_WAWebProtobufsDeviceCapabilities_proto_rawDescGZIP(), []int{0, 3}
return file_waDeviceCapabilities_WAWebProtobufsDeviceCapabilities_proto_rawDescGZIP(), []int{0, 4}
}
func (x *DeviceCapabilities_LIDMigration) GetChatDbMigrationTimestamp() uint64 {
@@ -495,20 +547,23 @@ var File_waDeviceCapabilities_WAWebProtobufsDeviceCapabilities_proto protoreflec
const file_waDeviceCapabilities_WAWebProtobufsDeviceCapabilities_proto_rawDesc = "" +
"\n" +
";waDeviceCapabilities/WAWebProtobufsDeviceCapabilities.proto\x12 WAWebProtobufsDeviceCapabilities\"\x93\v\n" +
";waDeviceCapabilities/WAWebProtobufsDeviceCapabilities.proto\x12 WAWebProtobufsDeviceCapabilities\"\xd2\f\n" +
"\x12DeviceCapabilities\x12}\n" +
"\x14chatLockSupportLevel\x18\x01 \x01(\x0e2I.WAWebProtobufsDeviceCapabilities.DeviceCapabilities.ChatLockSupportLevelR\x14chatLockSupportLevel\x12e\n" +
"\flidMigration\x18\x02 \x01(\v2A.WAWebProtobufsDeviceCapabilities.DeviceCapabilities.LIDMigrationR\flidMigration\x12t\n" +
"\x11businessBroadcast\x18\x03 \x01(\v2F.WAWebProtobufsDeviceCapabilities.DeviceCapabilities.BusinessBroadcastR\x11businessBroadcast\x12h\n" +
"\ruserHasAvatar\x18\x04 \x01(\v2B.WAWebProtobufsDeviceCapabilities.DeviceCapabilities.UserHasAvatarR\ruserHasAvatar\x12\x92\x01\n" +
"\x1bmemberNameTagPrimarySupport\x18\x05 \x01(\x0e2P.WAWebProtobufsDeviceCapabilities.DeviceCapabilities.MemberNameTagPrimarySupportR\x1bmemberNameTagPrimarySupport\x12Y\n" +
"\baiThread\x18\x06 \x01(\v2=.WAWebProtobufsDeviceCapabilities.DeviceCapabilities.AiThreadR\baiThread\x1a\xa9\x01\n" +
"\baiThread\x18\x06 \x01(\v2=.WAWebProtobufsDeviceCapabilities.DeviceCapabilities.AiThreadR\baiThread\x12n\n" +
"\x0faiFbidMigration\x18\a \x01(\v2D.WAWebProtobufsDeviceCapabilities.DeviceCapabilities.AiFbidMigrationR\x0faiFbidMigration\x1a\xa9\x01\n" +
"\bAiThread\x12n\n" +
"\fsupportLevel\x18\x01 \x01(\x0e2J.WAWebProtobufsDeviceCapabilities.DeviceCapabilities.AiThread.SupportLevelR\fsupportLevel\"-\n" +
"\fSupportLevel\x12\b\n" +
"\x04NONE\x10\x00\x12\t\n" +
"\x05INFRA\x10\x01\x12\b\n" +
"\x04FULL\x10\x02\x1a5\n" +
"\x04FULL\x10\x02\x1aM\n" +
"\x0fAiFbidMigration\x12:\n" +
"\x18chatDbMigrationTimestamp\x18\x01 \x01(\x04R\x18chatDbMigrationTimestamp\x1a5\n" +
"\rUserHasAvatar\x12$\n" +
"\ruserHasAvatar\x18\x01 \x01(\bR\ruserHasAvatar\x1a\x87\x02\n" +
"\x11BusinessBroadcast\x12,\n" +
@@ -541,30 +596,32 @@ func file_waDeviceCapabilities_WAWebProtobufsDeviceCapabilities_proto_rawDescGZI
}
var file_waDeviceCapabilities_WAWebProtobufsDeviceCapabilities_proto_enumTypes = make([]protoimpl.EnumInfo, 3)
var file_waDeviceCapabilities_WAWebProtobufsDeviceCapabilities_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
var file_waDeviceCapabilities_WAWebProtobufsDeviceCapabilities_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_waDeviceCapabilities_WAWebProtobufsDeviceCapabilities_proto_goTypes = []any{
(DeviceCapabilities_MemberNameTagPrimarySupport)(0), // 0: WAWebProtobufsDeviceCapabilities.DeviceCapabilities.MemberNameTagPrimarySupport
(DeviceCapabilities_ChatLockSupportLevel)(0), // 1: WAWebProtobufsDeviceCapabilities.DeviceCapabilities.ChatLockSupportLevel
(DeviceCapabilities_AiThread_SupportLevel)(0), // 2: WAWebProtobufsDeviceCapabilities.DeviceCapabilities.AiThread.SupportLevel
(*DeviceCapabilities)(nil), // 3: WAWebProtobufsDeviceCapabilities.DeviceCapabilities
(*DeviceCapabilities_AiThread)(nil), // 4: WAWebProtobufsDeviceCapabilities.DeviceCapabilities.AiThread
(*DeviceCapabilities_UserHasAvatar)(nil), // 5: WAWebProtobufsDeviceCapabilities.DeviceCapabilities.UserHasAvatar
(*DeviceCapabilities_BusinessBroadcast)(nil), // 6: WAWebProtobufsDeviceCapabilities.DeviceCapabilities.BusinessBroadcast
(*DeviceCapabilities_LIDMigration)(nil), // 7: WAWebProtobufsDeviceCapabilities.DeviceCapabilities.LIDMigration
(*DeviceCapabilities_AiFbidMigration)(nil), // 5: WAWebProtobufsDeviceCapabilities.DeviceCapabilities.AiFbidMigration
(*DeviceCapabilities_UserHasAvatar)(nil), // 6: WAWebProtobufsDeviceCapabilities.DeviceCapabilities.UserHasAvatar
(*DeviceCapabilities_BusinessBroadcast)(nil), // 7: WAWebProtobufsDeviceCapabilities.DeviceCapabilities.BusinessBroadcast
(*DeviceCapabilities_LIDMigration)(nil), // 8: WAWebProtobufsDeviceCapabilities.DeviceCapabilities.LIDMigration
}
var file_waDeviceCapabilities_WAWebProtobufsDeviceCapabilities_proto_depIdxs = []int32{
1, // 0: WAWebProtobufsDeviceCapabilities.DeviceCapabilities.chatLockSupportLevel:type_name -> WAWebProtobufsDeviceCapabilities.DeviceCapabilities.ChatLockSupportLevel
7, // 1: WAWebProtobufsDeviceCapabilities.DeviceCapabilities.lidMigration:type_name -> WAWebProtobufsDeviceCapabilities.DeviceCapabilities.LIDMigration
6, // 2: WAWebProtobufsDeviceCapabilities.DeviceCapabilities.businessBroadcast:type_name -> WAWebProtobufsDeviceCapabilities.DeviceCapabilities.BusinessBroadcast
5, // 3: WAWebProtobufsDeviceCapabilities.DeviceCapabilities.userHasAvatar:type_name -> WAWebProtobufsDeviceCapabilities.DeviceCapabilities.UserHasAvatar
8, // 1: WAWebProtobufsDeviceCapabilities.DeviceCapabilities.lidMigration:type_name -> WAWebProtobufsDeviceCapabilities.DeviceCapabilities.LIDMigration
7, // 2: WAWebProtobufsDeviceCapabilities.DeviceCapabilities.businessBroadcast:type_name -> WAWebProtobufsDeviceCapabilities.DeviceCapabilities.BusinessBroadcast
6, // 3: WAWebProtobufsDeviceCapabilities.DeviceCapabilities.userHasAvatar:type_name -> WAWebProtobufsDeviceCapabilities.DeviceCapabilities.UserHasAvatar
0, // 4: WAWebProtobufsDeviceCapabilities.DeviceCapabilities.memberNameTagPrimarySupport:type_name -> WAWebProtobufsDeviceCapabilities.DeviceCapabilities.MemberNameTagPrimarySupport
4, // 5: WAWebProtobufsDeviceCapabilities.DeviceCapabilities.aiThread:type_name -> WAWebProtobufsDeviceCapabilities.DeviceCapabilities.AiThread
2, // 6: WAWebProtobufsDeviceCapabilities.DeviceCapabilities.AiThread.supportLevel:type_name -> WAWebProtobufsDeviceCapabilities.DeviceCapabilities.AiThread.SupportLevel
7, // [7:7] is the sub-list for method output_type
7, // [7:7] is the sub-list for method input_type
7, // [7:7] is the sub-list for extension type_name
7, // [7:7] is the sub-list for extension extendee
0, // [0:7] is the sub-list for field type_name
5, // 6: WAWebProtobufsDeviceCapabilities.DeviceCapabilities.aiFbidMigration:type_name -> WAWebProtobufsDeviceCapabilities.DeviceCapabilities.AiFbidMigration
2, // 7: WAWebProtobufsDeviceCapabilities.DeviceCapabilities.AiThread.supportLevel:type_name -> WAWebProtobufsDeviceCapabilities.DeviceCapabilities.AiThread.SupportLevel
8, // [8:8] is the sub-list for method output_type
8, // [8:8] is the sub-list for method input_type
8, // [8:8] is the sub-list for extension type_name
8, // [8:8] is the sub-list for extension extendee
0, // [0:8] is the sub-list for field type_name
}
func init() { file_waDeviceCapabilities_WAWebProtobufsDeviceCapabilities_proto_init() }
@@ -578,7 +635,7 @@ func file_waDeviceCapabilities_WAWebProtobufsDeviceCapabilities_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_waDeviceCapabilities_WAWebProtobufsDeviceCapabilities_proto_rawDesc), len(file_waDeviceCapabilities_WAWebProtobufsDeviceCapabilities_proto_rawDesc)),
NumEnums: 3,
NumMessages: 5,
NumMessages: 6,
NumExtensions: 0,
NumServices: 0,
},
@@ -25,6 +25,10 @@ message DeviceCapabilities {
optional SupportLevel supportLevel = 1;
}
message AiFbidMigration {
optional uint64 chatDbMigrationTimestamp = 1;
}
message UserHasAvatar {
optional bool userHasAvatar = 1;
}
@@ -47,4 +51,5 @@ message DeviceCapabilities {
optional UserHasAvatar userHasAvatar = 4;
optional MemberNameTagPrimarySupport memberNameTagPrimarySupport = 5;
optional AiThread aiThread = 6;
optional AiFbidMigration aiFbidMigration = 7;
}
+2003 -1316
View File
File diff suppressed because it is too large. Load diff
+90 -21
View File
@@ -5,9 +5,11 @@ option go_package = "go.mau.fi/whatsmeow/proto/waE2E";
import "waAICommon/WAWebProtobufsAICommon.proto";
import "waAICommonDeprecated/WAAICommonDeprecated.proto";
import "waAdv/WAAdv.proto";
import "waAea/WAWebProtobufsAea.proto";
import "waCompanionReg/WACompanionReg.proto";
import "waMmsRetry/WAMmsRetry.proto";
import "waCommon/WACommon.proto";
import "waServerSync/WAWebProtobufsServerSync.proto";
import "waStatusAttributions/WAStatusAttributions.proto";
enum PollType {
@@ -405,6 +407,7 @@ message InteractiveMessage {
optional string uuid = 1;
optional string data = 2;
optional string type = 3;
optional string fallback = 4;
}
message Footer {
@@ -566,35 +569,33 @@ message SplitPaymentParticipant {
optional SplitPaymentStatus status = 3;
}
message P2PPaymentReminderNotification {
enum ReminderState {
UNKNOWN_STATE = 0;
message PaymentReminderMessage {
enum ReminderStatus {
REMINDER_STATUS_UNKNOWN = 0;
ACTIVE = 1;
PAUSED = 2;
STOPPED = 3;
CANCELLED_BY_CREATOR = 2;
STOPPED_BY_RECEIVER = 3;
EXPIRED = 4;
CANCELLED = 5;
PAID = 5;
}
enum ReminderFrequency {
UNKNOWN_FREQUENCY = 0;
REMINDER_FREQUENCY_UNKNOWN = 0;
WEEKLY = 1;
BIWEEKLY = 2;
BI_WEEKLY = 2;
MONTHLY = 3;
CUSTOM = 4;
QUARTERLY = 4;
}
optional string reminderID = 1;
optional Money amount = 2;
optional ReminderFrequency frequency = 3;
optional int64 nextReminderTimestamp = 4;
optional int64 expiryTimestamp = 5;
optional ReminderState state = 6;
optional string description = 7;
optional string creatorJID = 8;
optional string receiverJID = 9;
optional string upiID = 10;
optional int64 createdTimestamp = 11;
optional string instanceID = 2;
optional string description = 3;
optional ReminderFrequency frequency = 4;
optional ReminderStatus status = 5;
optional string payeeVpa = 6;
optional string payeeJID = 7;
optional string payerJID = 8;
optional Money amount = 9;
}
message PaymentInviteMessage {
@@ -938,6 +939,9 @@ message ProtocolMessage {
AI_MEDIA_COLLECTION_MESSAGE = 31;
MESSAGE_UNSCHEDULE = 32;
CHAT_THEME_SETTING = 34;
AI_METADATA_OPERATION = 35;
MARK_AS_VERIFIED_ACTION = 36;
COEX_STATE_SYNC = 37;
}
optional WACommon.MessageKey key = 1;
@@ -967,6 +971,9 @@ message ProtocolMessage {
optional WAWebProtobufsAICommon.AIMediaCollectionMessage aiMediaCollectionMessage = 28;
optional uint32 afterReadDuration = 29;
optional ChatThemeSetting chatThemeSetting = 30;
optional WAWebProtobufsAICommon.AIMetadataOperation aiMetadataOperation = 31;
optional MarkAsVerifiedAction markAsVerifiedAction = 32;
optional WAWebProtobufsServerSync.CoexStateSync coexStateSync = 33;
}
message CloudAPIThreadControlNotification {
@@ -1088,7 +1095,7 @@ message ExtendedTextMessage {
optional bool viewOnce = 30;
optional uint32 videoHeight = 31;
optional uint32 videoWidth = 32;
optional MMSThumbnailMetadata faviconMMSMetadata = 33;
optional MMSThumbnailMetadata faviconMmsMetadata = 33;
optional LinkPreviewMetadata linkPreviewMetadata = 34;
optional PaymentLinkMetadata paymentLinkMetadata = 35;
repeated VideoEndCard endCardTiles = 36;
@@ -1284,6 +1291,20 @@ message ContextInfo {
BESTSELLERS = 8;
MENU = 9;
ABOUT = 10;
SHOP = 11;
ORDER = 12;
}
message UnauthenticatedBusinessMetadata {
optional string businessName = 1;
optional string businessCategory = 2;
optional bool businessIsOpen = 3;
optional int64 businessIsOpenSnapshotMS = 4;
}
message SignedPayload {
optional string verifiedName = 1;
repeated Pill pills = 2;
}
message Pill {
@@ -1294,6 +1315,9 @@ message ContextInfo {
optional string businessJID = 1;
repeated Pill pills = 2;
optional EntryPoint entryPoint = 3;
optional bytes signedPayload = 4;
optional WAWebProtobufsAICommon.BotSignatureVerificationMetadata signatureEnvelope = 5;
optional UnauthenticatedBusinessMetadata unauthenticatedBusinessMetadata = 6;
}
message StatusAudienceMetadata {
@@ -1401,6 +1425,10 @@ message ContextInfo {
optional string caption = 17;
}
message InstagramThreadLink {
optional string URL = 1;
}
message PartiallySelectedContent {
optional string text = 1;
}
@@ -1490,6 +1518,8 @@ message ContextInfo {
optional CrossAppSource crossAppSource = 77;
optional BusinessInteractionPills businessInteractionPills = 78;
optional string posterStatusID = 79;
optional InstagramThreadLink instagramThreadLink = 80;
optional WAWebProtobufsAICommon.AIProvenance aiProvenance = 81;
}
message MessageAssociation {
@@ -1556,6 +1586,8 @@ message MessageContextInfo {
repeated ThreadID threadID = 15;
optional WebLinkRenderConfig weblinkRenderConfig = 16;
optional bytes teeBotMetadata = 17;
optional WAWebProtobufsAea.NonE2EEAttestation accountEncryptionAttestation = 18;
optional bytes associatedPrimaryIdentityKey = 19;
}
message InteractiveAnnotation {
@@ -1782,8 +1814,11 @@ message Message {
optional PollAddOptionMessage pollAddOptionMessage = 121;
optional EventInviteMessage eventInviteMessage = 122;
optional GroupRootKeyShare groupRootKeyShare = 123;
optional P2PPaymentReminderNotification p2PPaymentReminderNotification = 124;
optional PaymentReminderMessage paymentReminderMessage = 124;
optional SplitPaymentMessage splitPaymentMessage = 125;
optional FutureProofMessage newsletterAdminProfileStatusMessage = 126;
optional RootSecretDistributeMessage rootSecretDistributeMessage = 127;
optional SplitPaymentUpdateMessage splitPaymentUpdateMessage = 128;
}
message AlbumMessage {
@@ -1800,9 +1835,21 @@ message MessageHistoryMetadata {
optional int64 oldestMessageTimestampInBundle = 5;
}
message HistoryShareMessageEntry {
optional string stanzaID = 1;
optional bytes messageSecretProof = 2;
}
message BotHistoryShareSyncMetadata {
optional string botJID = 1;
optional int64 historyShareCutoffTimestamp = 2;
repeated HistoryShareMessageEntry historyShareMessages = 3;
}
message MessageHistoryNotice {
optional ContextInfo contextInfo = 1;
optional MessageHistoryMetadata messageHistoryMetadata = 2;
optional BotHistoryShareSyncMetadata botHistoryShareSyncMetadata = 3;
}
message MessageHistoryBundle {
@@ -1885,6 +1932,7 @@ message PollResultSnapshotMessage {
message PollAddOptionMessage {
optional WACommon.MessageKey pollCreationMessageKey = 1;
optional PollCreationMessage.Option addOption = 2;
optional PollUpdateMessageMetadata metadata = 3;
}
message PollVoteMessage {
@@ -1897,6 +1945,8 @@ message PollEncValue {
}
message PollUpdateMessageMetadata {
optional bytes pollNameHash = 1;
optional string lastEditStanzaID = 2;
}
message PollUpdateMessage {
@@ -1961,6 +2011,7 @@ message EventInviteMessage {
optional string caption = 6;
optional bool isCanceled = 7;
optional int64 endTime = 8;
optional string callLink = 9;
}
message NewsletterFollowerInviteMessage {
@@ -2098,6 +2149,11 @@ message LiveLocationMessage {
optional ContextInfo contextInfo = 17;
}
message SplitPaymentUpdateMessage {
optional string splitID = 1;
optional string participantJID = 2;
}
message SplitPaymentMessage {
optional string splitID = 1;
optional Money totalAmount = 2;
@@ -2246,6 +2302,13 @@ message ChatThemeSetting {
optional string colorSchemeID = 3;
}
message MarkAsVerifiedAction {
optional string userJIDString = 1;
optional bool verified = 2;
optional bytes verifiedIdentityKey = 3;
optional uint64 actionSeq = 4;
}
message Chat {
optional string displayName = 1;
optional string ID = 2;
@@ -2315,6 +2378,7 @@ message URLMetadata {
message PaymentExtendedMetadata {
optional uint32 type = 1;
optional string platform = 2;
optional string messageParamsJSON = 3;
}
message MMSThumbnailMetadata {
@@ -2349,6 +2413,10 @@ message ContactMessage {
optional bool isSelfContact = 18;
}
message RootSecretDistributeMessage {
optional string chatJID = 1;
}
message SenderKeyDistributionMessage {
optional string groupID = 1;
optional bytes axolotlSenderKeyDistributionMessage = 2;
@@ -2518,4 +2586,5 @@ message GroupRootKeyShareEntry {
optional bytes groupRootKey = 1;
optional string keyID = 2;
optional int64 expiryTimestampMS = 3;
optional int64 createdTimestampMS = 4;
}
+158 -92
View File
@@ -772,6 +772,7 @@ type Conversation struct {
AppealUpdateTime *uint64 `protobuf:"varint,60,opt,name=appealUpdateTime" json:"appealUpdateTime,omitempty"`
AuthAgentParentCompanyName *string `protobuf:"bytes,61,opt,name=authAgentParentCompanyName" json:"authAgentParentCompanyName,omitempty"`
AuthAgentObaPhoneNumber *string `protobuf:"bytes,62,opt,name=authAgentObaPhoneNumber" json:"authAgentObaPhoneNumber,omitempty"`
IdentityVerification *IdentityVerificationState `protobuf:"bytes,63,opt,name=identityVerification" json:"identityVerification,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
@@ -1240,6 +1241,13 @@ func (x *Conversation) GetAuthAgentObaPhoneNumber() string {
return ""
}
func (x *Conversation) GetIdentityVerification() *IdentityVerificationState {
if x != nil {
return x.IdentityVerification
}
return nil
}
type GroupParticipant struct {
state protoimpl.MessageState `protogen:"open.v1"`
UserJID *string `protobuf:"bytes,1,req,name=userJID" json:"userJID,omitempty"`
@@ -1360,6 +1368,58 @@ func (x *PastParticipant) GetLeaveTS() uint64 {
return 0
}
type IdentityVerificationState struct {
state protoimpl.MessageState `protogen:"open.v1"`
Verified *bool `protobuf:"varint,1,opt,name=verified" json:"verified,omitempty"`
ActionSeq *uint64 `protobuf:"varint,2,opt,name=actionSeq" json:"actionSeq,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *IdentityVerificationState) Reset() {
*x = IdentityVerificationState{}
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *IdentityVerificationState) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*IdentityVerificationState) ProtoMessage() {}
func (x *IdentityVerificationState) ProtoReflect() protoreflect.Message {
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[4]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use IdentityVerificationState.ProtoReflect.Descriptor instead.
func (*IdentityVerificationState) Descriptor() ([]byte, []int) {
return file_waHistorySync_WAWebProtobufsHistorySync_proto_rawDescGZIP(), []int{4}
}
func (x *IdentityVerificationState) GetVerified() bool {
if x != nil && x.Verified != nil {
return *x.Verified
}
return false
}
func (x *IdentityVerificationState) GetActionSeq() uint64 {
if x != nil && x.ActionSeq != nil {
return *x.ActionSeq
}
return 0
}
type PhoneNumberToLIDMapping struct {
state protoimpl.MessageState `protogen:"open.v1"`
PnJID *string `protobuf:"bytes,1,opt,name=pnJID" json:"pnJID,omitempty"`
@@ -1370,7 +1430,7 @@ type PhoneNumberToLIDMapping struct {
func (x *PhoneNumberToLIDMapping) Reset() {
*x = PhoneNumberToLIDMapping{}
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[4]
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1382,7 +1442,7 @@ func (x *PhoneNumberToLIDMapping) String() string {
func (*PhoneNumberToLIDMapping) ProtoMessage() {}
func (x *PhoneNumberToLIDMapping) ProtoReflect() protoreflect.Message {
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[4]
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[5]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1395,7 +1455,7 @@ func (x *PhoneNumberToLIDMapping) ProtoReflect() protoreflect.Message {
// Deprecated: Use PhoneNumberToLIDMapping.ProtoReflect.Descriptor instead.
func (*PhoneNumberToLIDMapping) Descriptor() ([]byte, []int) {
return file_waHistorySync_WAWebProtobufsHistorySync_proto_rawDescGZIP(), []int{4}
return file_waHistorySync_WAWebProtobufsHistorySync_proto_rawDescGZIP(), []int{5}
}
func (x *PhoneNumberToLIDMapping) GetPnJID() string {
@@ -1425,7 +1485,7 @@ type InlineContact struct {
func (x *InlineContact) Reset() {
*x = InlineContact{}
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[5]
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1437,7 +1497,7 @@ func (x *InlineContact) String() string {
func (*InlineContact) ProtoMessage() {}
func (x *InlineContact) ProtoReflect() protoreflect.Message {
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[5]
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[6]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1450,7 +1510,7 @@ func (x *InlineContact) ProtoReflect() protoreflect.Message {
// Deprecated: Use InlineContact.ProtoReflect.Descriptor instead.
func (*InlineContact) Descriptor() ([]byte, []int) {
return file_waHistorySync_WAWebProtobufsHistorySync_proto_rawDescGZIP(), []int{5}
return file_waHistorySync_WAWebProtobufsHistorySync_proto_rawDescGZIP(), []int{6}
}
func (x *InlineContact) GetPnJID() string {
@@ -1500,7 +1560,7 @@ type Account struct {
func (x *Account) Reset() {
*x = Account{}
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[6]
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1512,7 +1572,7 @@ func (x *Account) String() string {
func (*Account) ProtoMessage() {}
func (x *Account) ProtoReflect() protoreflect.Message {
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[6]
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[7]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1525,7 +1585,7 @@ func (x *Account) ProtoReflect() protoreflect.Message {
// Deprecated: Use Account.ProtoReflect.Descriptor instead.
func (*Account) Descriptor() ([]byte, []int) {
return file_waHistorySync_WAWebProtobufsHistorySync_proto_rawDescGZIP(), []int{6}
return file_waHistorySync_WAWebProtobufsHistorySync_proto_rawDescGZIP(), []int{7}
}
func (x *Account) GetLid() string {
@@ -1566,7 +1626,7 @@ type HistorySyncMsg struct {
func (x *HistorySyncMsg) Reset() {
*x = HistorySyncMsg{}
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[7]
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1578,7 +1638,7 @@ func (x *HistorySyncMsg) String() string {
func (*HistorySyncMsg) ProtoMessage() {}
func (x *HistorySyncMsg) ProtoReflect() protoreflect.Message {
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[7]
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[8]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1591,7 +1651,7 @@ func (x *HistorySyncMsg) ProtoReflect() protoreflect.Message {
// Deprecated: Use HistorySyncMsg.ProtoReflect.Descriptor instead.
func (*HistorySyncMsg) Descriptor() ([]byte, []int) {
return file_waHistorySync_WAWebProtobufsHistorySync_proto_rawDescGZIP(), []int{7}
return file_waHistorySync_WAWebProtobufsHistorySync_proto_rawDescGZIP(), []int{8}
}
func (x *HistorySyncMsg) GetMessage() *waWeb.WebMessageInfo {
@@ -1618,7 +1678,7 @@ type Pushname struct {
func (x *Pushname) Reset() {
*x = Pushname{}
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[8]
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1630,7 +1690,7 @@ func (x *Pushname) String() string {
func (*Pushname) ProtoMessage() {}
func (x *Pushname) ProtoReflect() protoreflect.Message {
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[8]
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[9]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1643,7 +1703,7 @@ func (x *Pushname) ProtoReflect() protoreflect.Message {
// Deprecated: Use Pushname.ProtoReflect.Descriptor instead.
func (*Pushname) Descriptor() ([]byte, []int) {
return file_waHistorySync_WAWebProtobufsHistorySync_proto_rawDescGZIP(), []int{8}
return file_waHistorySync_WAWebProtobufsHistorySync_proto_rawDescGZIP(), []int{9}
}
func (x *Pushname) GetID() string {
@@ -1671,7 +1731,7 @@ type WallpaperSettings struct {
func (x *WallpaperSettings) Reset() {
*x = WallpaperSettings{}
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[9]
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1683,7 +1743,7 @@ func (x *WallpaperSettings) String() string {
func (*WallpaperSettings) ProtoMessage() {}
func (x *WallpaperSettings) ProtoReflect() protoreflect.Message {
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[9]
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[10]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1696,7 +1756,7 @@ func (x *WallpaperSettings) ProtoReflect() protoreflect.Message {
// Deprecated: Use WallpaperSettings.ProtoReflect.Descriptor instead.
func (*WallpaperSettings) Descriptor() ([]byte, []int) {
return file_waHistorySync_WAWebProtobufsHistorySync_proto_rawDescGZIP(), []int{9}
return file_waHistorySync_WAWebProtobufsHistorySync_proto_rawDescGZIP(), []int{10}
}
func (x *WallpaperSettings) GetFilename() string {
@@ -1748,7 +1808,7 @@ type GlobalSettings struct {
func (x *GlobalSettings) Reset() {
*x = GlobalSettings{}
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[10]
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1760,7 +1820,7 @@ func (x *GlobalSettings) String() string {
func (*GlobalSettings) ProtoMessage() {}
func (x *GlobalSettings) ProtoReflect() protoreflect.Message {
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[10]
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[11]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1773,7 +1833,7 @@ func (x *GlobalSettings) ProtoReflect() protoreflect.Message {
// Deprecated: Use GlobalSettings.ProtoReflect.Descriptor instead.
func (*GlobalSettings) Descriptor() ([]byte, []int) {
return file_waHistorySync_WAWebProtobufsHistorySync_proto_rawDescGZIP(), []int{10}
return file_waHistorySync_WAWebProtobufsHistorySync_proto_rawDescGZIP(), []int{11}
}
func (x *GlobalSettings) GetLightThemeWallpaper() *WallpaperSettings {
@@ -1928,7 +1988,7 @@ type AutoDownloadSettings struct {
func (x *AutoDownloadSettings) Reset() {
*x = AutoDownloadSettings{}
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[11]
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[12]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1940,7 +2000,7 @@ func (x *AutoDownloadSettings) String() string {
func (*AutoDownloadSettings) ProtoMessage() {}
func (x *AutoDownloadSettings) ProtoReflect() protoreflect.Message {
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[11]
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[12]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1953,7 +2013,7 @@ func (x *AutoDownloadSettings) ProtoReflect() protoreflect.Message {
// Deprecated: Use AutoDownloadSettings.ProtoReflect.Descriptor instead.
func (*AutoDownloadSettings) Descriptor() ([]byte, []int) {
return file_waHistorySync_WAWebProtobufsHistorySync_proto_rawDescGZIP(), []int{11}
return file_waHistorySync_WAWebProtobufsHistorySync_proto_rawDescGZIP(), []int{12}
}
func (x *AutoDownloadSettings) GetDownloadImages() bool {
@@ -2006,7 +2066,7 @@ type StickerMetadata struct {
func (x *StickerMetadata) Reset() {
*x = StickerMetadata{}
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[12]
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[13]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2018,7 +2078,7 @@ func (x *StickerMetadata) String() string {
func (*StickerMetadata) ProtoMessage() {}
func (x *StickerMetadata) ProtoReflect() protoreflect.Message {
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[12]
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[13]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2031,7 +2091,7 @@ func (x *StickerMetadata) ProtoReflect() protoreflect.Message {
// Deprecated: Use StickerMetadata.ProtoReflect.Descriptor instead.
func (*StickerMetadata) Descriptor() ([]byte, []int) {
return file_waHistorySync_WAWebProtobufsHistorySync_proto_rawDescGZIP(), []int{12}
return file_waHistorySync_WAWebProtobufsHistorySync_proto_rawDescGZIP(), []int{13}
}
func (x *StickerMetadata) GetURL() string {
@@ -2142,7 +2202,7 @@ type PastParticipants struct {
func (x *PastParticipants) Reset() {
*x = PastParticipants{}
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[13]
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[14]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2154,7 +2214,7 @@ func (x *PastParticipants) String() string {
func (*PastParticipants) ProtoMessage() {}
func (x *PastParticipants) ProtoReflect() protoreflect.Message {
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[13]
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[14]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2167,7 +2227,7 @@ func (x *PastParticipants) ProtoReflect() protoreflect.Message {
// Deprecated: Use PastParticipants.ProtoReflect.Descriptor instead.
func (*PastParticipants) Descriptor() ([]byte, []int) {
return file_waHistorySync_WAWebProtobufsHistorySync_proto_rawDescGZIP(), []int{13}
return file_waHistorySync_WAWebProtobufsHistorySync_proto_rawDescGZIP(), []int{14}
}
func (x *PastParticipants) GetGroupJID() string {
@@ -2194,7 +2254,7 @@ type AvatarUserSettings struct {
func (x *AvatarUserSettings) Reset() {
*x = AvatarUserSettings{}
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[14]
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[15]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2206,7 +2266,7 @@ func (x *AvatarUserSettings) String() string {
func (*AvatarUserSettings) ProtoMessage() {}
func (x *AvatarUserSettings) ProtoReflect() protoreflect.Message {
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[14]
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[15]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2219,7 +2279,7 @@ func (x *AvatarUserSettings) ProtoReflect() protoreflect.Message {
// Deprecated: Use AvatarUserSettings.ProtoReflect.Descriptor instead.
func (*AvatarUserSettings) Descriptor() ([]byte, []int) {
return file_waHistorySync_WAWebProtobufsHistorySync_proto_rawDescGZIP(), []int{14}
return file_waHistorySync_WAWebProtobufsHistorySync_proto_rawDescGZIP(), []int{15}
}
func (x *AvatarUserSettings) GetFBID() string {
@@ -2250,7 +2310,7 @@ type NotificationSettings struct {
func (x *NotificationSettings) Reset() {
*x = NotificationSettings{}
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[15]
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[16]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2262,7 +2322,7 @@ func (x *NotificationSettings) String() string {
func (*NotificationSettings) ProtoMessage() {}
func (x *NotificationSettings) ProtoReflect() protoreflect.Message {
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[15]
mi := &file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes[16]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2275,7 +2335,7 @@ func (x *NotificationSettings) ProtoReflect() protoreflect.Message {
// Deprecated: Use NotificationSettings.ProtoReflect.Descriptor instead.
func (*NotificationSettings) Descriptor() ([]byte, []int) {
return file_waHistorySync_WAWebProtobufsHistorySync_proto_rawDescGZIP(), []int{15}
return file_waHistorySync_WAWebProtobufsHistorySync_proto_rawDescGZIP(), []int{16}
}
func (x *NotificationSettings) GetMessageVibrate() string {
@@ -2360,7 +2420,7 @@ const file_waHistorySync_WAWebProtobufsHistorySync_proto_rawDesc = "" +
"\x06RECENT\x10\x03\x12\r\n" +
"\tPUSH_NAME\x10\x04\x12\x15\n" +
"\x11NON_BLOCKING_DATA\x10\x05\x12\r\n" +
"\tON_DEMAND\x10\x06\"\xb2\x19\n" +
"\tON_DEMAND\x10\x06\"\x9c\x1a\n" +
"\fConversation\x12\x0e\n" +
"\x02ID\x18\x01 \x02(\tR\x02ID\x12E\n" +
"\bmessages\x18\x02 \x03(\v2).WAWebProtobufsHistorySync.HistorySyncMsgR\bmessages\x12\x16\n" +
@@ -2430,7 +2490,8 @@ const file_waHistorySync_WAWebProtobufsHistorySync_proto_rawDesc = "" +
"\fappealStatus\x18; \x01(\x0e29.WAWebProtobufsHistorySync.Conversation.GroupAppealStatusR\fappealStatus\x12*\n" +
"\x10appealUpdateTime\x18< \x01(\x04R\x10appealUpdateTime\x12>\n" +
"\x1aauthAgentParentCompanyName\x18= \x01(\tR\x1aauthAgentParentCompanyName\x128\n" +
"\x17authAgentObaPhoneNumber\x18> \x01(\tR\x17authAgentObaPhoneNumber\"b\n" +
"\x17authAgentObaPhoneNumber\x18> \x01(\tR\x17authAgentObaPhoneNumber\x12h\n" +
"\x14identityVerification\x18? \x01(\v24.WAWebProtobufsHistorySync.IdentityVerificationStateR\x14identityVerification\"b\n" +
"\x11GroupAppealStatus\x12\r\n" +
"\tNO_APPEAL\x10\x00\x12\x14\n" +
"\x10APPEAL_IN_REVIEW\x10\x01\x12\x13\n" +
@@ -2456,7 +2517,10 @@ const file_waHistorySync_WAWebProtobufsHistorySync_proto_rawDesc = "" +
"\aleaveTS\x18\x03 \x01(\x04R\aleaveTS\"$\n" +
"\vLeaveReason\x12\b\n" +
"\x04LEFT\x10\x00\x12\v\n" +
"\aREMOVED\x10\x01\"G\n" +
"\aREMOVED\x10\x01\"U\n" +
"\x19IdentityVerificationState\x12\x1a\n" +
"\bverified\x18\x01 \x01(\bR\bverified\x12\x1c\n" +
"\tactionSeq\x18\x02 \x01(\x04R\tactionSeq\"G\n" +
"\x17PhoneNumberToLIDMapping\x12\x14\n" +
"\x05pnJID\x18\x01 \x01(\tR\x05pnJID\x12\x16\n" +
"\x06lidJID\x18\x02 \x01(\tR\x06lidJID\"\x93\x01\n" +
@@ -2568,7 +2632,7 @@ func file_waHistorySync_WAWebProtobufsHistorySync_proto_rawDescGZIP() []byte {
}
var file_waHistorySync_WAWebProtobufsHistorySync_proto_enumTypes = make([]protoimpl.EnumInfo, 8)
var file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes = make([]protoimpl.MessageInfo, 16)
var file_waHistorySync_WAWebProtobufsHistorySync_proto_msgTypes = make([]protoimpl.MessageInfo, 17)
var file_waHistorySync_WAWebProtobufsHistorySync_proto_goTypes = []any{
(MediaVisibility)(0), // 0: WAWebProtobufsHistorySync.MediaVisibility
(PrivacySystemMessage)(0), // 1: WAWebProtobufsHistorySync.PrivacySystemMessage
@@ -2582,67 +2646,69 @@ var file_waHistorySync_WAWebProtobufsHistorySync_proto_goTypes = []any{
(*Conversation)(nil), // 9: WAWebProtobufsHistorySync.Conversation
(*GroupParticipant)(nil), // 10: WAWebProtobufsHistorySync.GroupParticipant
(*PastParticipant)(nil), // 11: WAWebProtobufsHistorySync.PastParticipant
(*PhoneNumberToLIDMapping)(nil), // 12: WAWebProtobufsHistorySync.PhoneNumberToLIDMapping
(*InlineContact)(nil), // 13: WAWebProtobufsHistorySync.InlineContact
(*Account)(nil), // 14: WAWebProtobufsHistorySync.Account
(*HistorySyncMsg)(nil), // 15: WAWebProtobufsHistorySync.HistorySyncMsg
(*Pushname)(nil), // 16: WAWebProtobufsHistorySync.Pushname
(*WallpaperSettings)(nil), // 17: WAWebProtobufsHistorySync.WallpaperSettings
(*GlobalSettings)(nil), // 18: WAWebProtobufsHistorySync.GlobalSettings
(*AutoDownloadSettings)(nil), // 19: WAWebProtobufsHistorySync.AutoDownloadSettings
(*StickerMetadata)(nil), // 20: WAWebProtobufsHistorySync.StickerMetadata
(*PastParticipants)(nil), // 21: WAWebProtobufsHistorySync.PastParticipants
(*AvatarUserSettings)(nil), // 22: WAWebProtobufsHistorySync.AvatarUserSettings
(*NotificationSettings)(nil), // 23: WAWebProtobufsHistorySync.NotificationSettings
(*waWeb.WebMessageInfo)(nil), // 24: WAWebProtobufsWeb.WebMessageInfo
(*waSyncAction.CallLogRecord)(nil), // 25: WAWebProtobufSyncAction.CallLogRecord
(*waE2E.DisappearingMode)(nil), // 26: WAWebProtobufsE2E.DisappearingMode
(waCommon.LimitSharing_Trigger)(0), // 27: WACommon.LimitSharing.Trigger
(*waE2E.MemberLabel)(nil), // 28: WAWebProtobufsE2E.MemberLabel
(*waChatLockSettings.ChatLockSettings)(nil), // 29: WAWebProtobufsChatLockSettings.ChatLockSettings
(*IdentityVerificationState)(nil), // 12: WAWebProtobufsHistorySync.IdentityVerificationState
(*PhoneNumberToLIDMapping)(nil), // 13: WAWebProtobufsHistorySync.PhoneNumberToLIDMapping
(*InlineContact)(nil), // 14: WAWebProtobufsHistorySync.InlineContact
(*Account)(nil), // 15: WAWebProtobufsHistorySync.Account
(*HistorySyncMsg)(nil), // 16: WAWebProtobufsHistorySync.HistorySyncMsg
(*Pushname)(nil), // 17: WAWebProtobufsHistorySync.Pushname
(*WallpaperSettings)(nil), // 18: WAWebProtobufsHistorySync.WallpaperSettings
(*GlobalSettings)(nil), // 19: WAWebProtobufsHistorySync.GlobalSettings
(*AutoDownloadSettings)(nil), // 20: WAWebProtobufsHistorySync.AutoDownloadSettings
(*StickerMetadata)(nil), // 21: WAWebProtobufsHistorySync.StickerMetadata
(*PastParticipants)(nil), // 22: WAWebProtobufsHistorySync.PastParticipants
(*AvatarUserSettings)(nil), // 23: WAWebProtobufsHistorySync.AvatarUserSettings
(*NotificationSettings)(nil), // 24: WAWebProtobufsHistorySync.NotificationSettings
(*waWeb.WebMessageInfo)(nil), // 25: WAWebProtobufsWeb.WebMessageInfo
(*waSyncAction.CallLogRecord)(nil), // 26: WAWebProtobufSyncAction.CallLogRecord
(*waE2E.DisappearingMode)(nil), // 27: WAWebProtobufsE2E.DisappearingMode
(waCommon.LimitSharing_Trigger)(0), // 28: WACommon.LimitSharing.Trigger
(*waE2E.MemberLabel)(nil), // 29: WAWebProtobufsE2E.MemberLabel
(*waChatLockSettings.ChatLockSettings)(nil), // 30: WAWebProtobufsChatLockSettings.ChatLockSettings
}
var file_waHistorySync_WAWebProtobufsHistorySync_proto_depIdxs = []int32{
3, // 0: WAWebProtobufsHistorySync.HistorySync.syncType:type_name -> WAWebProtobufsHistorySync.HistorySync.HistorySyncType
9, // 1: WAWebProtobufsHistorySync.HistorySync.conversations:type_name -> WAWebProtobufsHistorySync.Conversation
24, // 2: WAWebProtobufsHistorySync.HistorySync.statusV3Messages:type_name -> WAWebProtobufsWeb.WebMessageInfo
16, // 3: WAWebProtobufsHistorySync.HistorySync.pushnames:type_name -> WAWebProtobufsHistorySync.Pushname
18, // 4: WAWebProtobufsHistorySync.HistorySync.globalSettings:type_name -> WAWebProtobufsHistorySync.GlobalSettings
20, // 5: WAWebProtobufsHistorySync.HistorySync.recentStickers:type_name -> WAWebProtobufsHistorySync.StickerMetadata
21, // 6: WAWebProtobufsHistorySync.HistorySync.pastParticipants:type_name -> WAWebProtobufsHistorySync.PastParticipants
25, // 7: WAWebProtobufsHistorySync.HistorySync.callLogRecords:type_name -> WAWebProtobufSyncAction.CallLogRecord
25, // 2: WAWebProtobufsHistorySync.HistorySync.statusV3Messages:type_name -> WAWebProtobufsWeb.WebMessageInfo
17, // 3: WAWebProtobufsHistorySync.HistorySync.pushnames:type_name -> WAWebProtobufsHistorySync.Pushname
19, // 4: WAWebProtobufsHistorySync.HistorySync.globalSettings:type_name -> WAWebProtobufsHistorySync.GlobalSettings
21, // 5: WAWebProtobufsHistorySync.HistorySync.recentStickers:type_name -> WAWebProtobufsHistorySync.StickerMetadata
22, // 6: WAWebProtobufsHistorySync.HistorySync.pastParticipants:type_name -> WAWebProtobufsHistorySync.PastParticipants
26, // 7: WAWebProtobufsHistorySync.HistorySync.callLogRecords:type_name -> WAWebProtobufSyncAction.CallLogRecord
2, // 8: WAWebProtobufsHistorySync.HistorySync.aiWaitListState:type_name -> WAWebProtobufsHistorySync.HistorySync.BotAIWaitListState
12, // 9: WAWebProtobufsHistorySync.HistorySync.phoneNumberToLidMappings:type_name -> WAWebProtobufsHistorySync.PhoneNumberToLIDMapping
14, // 10: WAWebProtobufsHistorySync.HistorySync.accounts:type_name -> WAWebProtobufsHistorySync.Account
13, // 11: WAWebProtobufsHistorySync.HistorySync.inlineContacts:type_name -> WAWebProtobufsHistorySync.InlineContact
15, // 12: WAWebProtobufsHistorySync.Conversation.messages:type_name -> WAWebProtobufsHistorySync.HistorySyncMsg
13, // 9: WAWebProtobufsHistorySync.HistorySync.phoneNumberToLidMappings:type_name -> WAWebProtobufsHistorySync.PhoneNumberToLIDMapping
15, // 10: WAWebProtobufsHistorySync.HistorySync.accounts:type_name -> WAWebProtobufsHistorySync.Account
14, // 11: WAWebProtobufsHistorySync.HistorySync.inlineContacts:type_name -> WAWebProtobufsHistorySync.InlineContact
16, // 12: WAWebProtobufsHistorySync.Conversation.messages:type_name -> WAWebProtobufsHistorySync.HistorySyncMsg
5, // 13: WAWebProtobufsHistorySync.Conversation.endOfHistoryTransferType:type_name -> WAWebProtobufsHistorySync.Conversation.EndOfHistoryTransferType
26, // 14: WAWebProtobufsHistorySync.Conversation.disappearingMode:type_name -> WAWebProtobufsE2E.DisappearingMode
27, // 14: WAWebProtobufsHistorySync.Conversation.disappearingMode:type_name -> WAWebProtobufsE2E.DisappearingMode
10, // 15: WAWebProtobufsHistorySync.Conversation.participant:type_name -> WAWebProtobufsHistorySync.GroupParticipant
17, // 16: WAWebProtobufsHistorySync.Conversation.wallpaper:type_name -> WAWebProtobufsHistorySync.WallpaperSettings
18, // 16: WAWebProtobufsHistorySync.Conversation.wallpaper:type_name -> WAWebProtobufsHistorySync.WallpaperSettings
0, // 17: WAWebProtobufsHistorySync.Conversation.mediaVisibility:type_name -> WAWebProtobufsHistorySync.MediaVisibility
1, // 18: WAWebProtobufsHistorySync.Conversation.systemMessageToInsert:type_name -> WAWebProtobufsHistorySync.PrivacySystemMessage
27, // 19: WAWebProtobufsHistorySync.Conversation.limitSharingTrigger:type_name -> WACommon.LimitSharing.Trigger
28, // 19: WAWebProtobufsHistorySync.Conversation.limitSharingTrigger:type_name -> WACommon.LimitSharing.Trigger
4, // 20: WAWebProtobufsHistorySync.Conversation.appealStatus:type_name -> WAWebProtobufsHistorySync.Conversation.GroupAppealStatus
6, // 21: WAWebProtobufsHistorySync.GroupParticipant.rank:type_name -> WAWebProtobufsHistorySync.GroupParticipant.Rank
28, // 22: WAWebProtobufsHistorySync.GroupParticipant.memberLabel:type_name -> WAWebProtobufsE2E.MemberLabel
7, // 23: WAWebProtobufsHistorySync.PastParticipant.leaveReason:type_name -> WAWebProtobufsHistorySync.PastParticipant.LeaveReason
24, // 24: WAWebProtobufsHistorySync.HistorySyncMsg.message:type_name -> WAWebProtobufsWeb.WebMessageInfo
17, // 25: WAWebProtobufsHistorySync.GlobalSettings.lightThemeWallpaper:type_name -> WAWebProtobufsHistorySync.WallpaperSettings
0, // 26: WAWebProtobufsHistorySync.GlobalSettings.mediaVisibility:type_name -> WAWebProtobufsHistorySync.MediaVisibility
17, // 27: WAWebProtobufsHistorySync.GlobalSettings.darkThemeWallpaper:type_name -> WAWebProtobufsHistorySync.WallpaperSettings
19, // 28: WAWebProtobufsHistorySync.GlobalSettings.autoDownloadWiFi:type_name -> WAWebProtobufsHistorySync.AutoDownloadSettings
19, // 29: WAWebProtobufsHistorySync.GlobalSettings.autoDownloadCellular:type_name -> WAWebProtobufsHistorySync.AutoDownloadSettings
19, // 30: WAWebProtobufsHistorySync.GlobalSettings.autoDownloadRoaming:type_name -> WAWebProtobufsHistorySync.AutoDownloadSettings
22, // 31: WAWebProtobufsHistorySync.GlobalSettings.avatarUserSettings:type_name -> WAWebProtobufsHistorySync.AvatarUserSettings
23, // 32: WAWebProtobufsHistorySync.GlobalSettings.individualNotificationSettings:type_name -> WAWebProtobufsHistorySync.NotificationSettings
23, // 33: WAWebProtobufsHistorySync.GlobalSettings.groupNotificationSettings:type_name -> WAWebProtobufsHistorySync.NotificationSettings
29, // 34: WAWebProtobufsHistorySync.GlobalSettings.chatLockSettings:type_name -> WAWebProtobufsChatLockSettings.ChatLockSettings
11, // 35: WAWebProtobufsHistorySync.PastParticipants.pastParticipants:type_name -> WAWebProtobufsHistorySync.PastParticipant
36, // [36:36] is the sub-list for method output_type
36, // [36:36] is the sub-list for method input_type
36, // [36:36] is the sub-list for extension type_name
36, // [36:36] is the sub-list for extension extendee
0, // [0:36] is the sub-list for field type_name
12, // 21: WAWebProtobufsHistorySync.Conversation.identityVerification:type_name -> WAWebProtobufsHistorySync.IdentityVerificationState
6, // 22: WAWebProtobufsHistorySync.GroupParticipant.rank:type_name -> WAWebProtobufsHistorySync.GroupParticipant.Rank
29, // 23: WAWebProtobufsHistorySync.GroupParticipant.memberLabel:type_name -> WAWebProtobufsE2E.MemberLabel
7, // 24: WAWebProtobufsHistorySync.PastParticipant.leaveReason:type_name -> WAWebProtobufsHistorySync.PastParticipant.LeaveReason
25, // 25: WAWebProtobufsHistorySync.HistorySyncMsg.message:type_name -> WAWebProtobufsWeb.WebMessageInfo
18, // 26: WAWebProtobufsHistorySync.GlobalSettings.lightThemeWallpaper:type_name -> WAWebProtobufsHistorySync.WallpaperSettings
0, // 27: WAWebProtobufsHistorySync.GlobalSettings.mediaVisibility:type_name -> WAWebProtobufsHistorySync.MediaVisibility
18, // 28: WAWebProtobufsHistorySync.GlobalSettings.darkThemeWallpaper:type_name -> WAWebProtobufsHistorySync.WallpaperSettings
20, // 29: WAWebProtobufsHistorySync.GlobalSettings.autoDownloadWiFi:type_name -> WAWebProtobufsHistorySync.AutoDownloadSettings
20, // 30: WAWebProtobufsHistorySync.GlobalSettings.autoDownloadCellular:type_name -> WAWebProtobufsHistorySync.AutoDownloadSettings
20, // 31: WAWebProtobufsHistorySync.GlobalSettings.autoDownloadRoaming:type_name -> WAWebProtobufsHistorySync.AutoDownloadSettings
23, // 32: WAWebProtobufsHistorySync.GlobalSettings.avatarUserSettings:type_name -> WAWebProtobufsHistorySync.AvatarUserSettings
24, // 33: WAWebProtobufsHistorySync.GlobalSettings.individualNotificationSettings:type_name -> WAWebProtobufsHistorySync.NotificationSettings
24, // 34: WAWebProtobufsHistorySync.GlobalSettings.groupNotificationSettings:type_name -> WAWebProtobufsHistorySync.NotificationSettings
30, // 35: WAWebProtobufsHistorySync.GlobalSettings.chatLockSettings:type_name -> WAWebProtobufsChatLockSettings.ChatLockSettings
11, // 36: WAWebProtobufsHistorySync.PastParticipants.pastParticipants:type_name -> WAWebProtobufsHistorySync.PastParticipant
37, // [37:37] is the sub-list for method output_type
37, // [37:37] is the sub-list for method input_type
37, // [37:37] is the sub-list for extension type_name
37, // [37:37] is the sub-list for extension extendee
0, // [0:37] is the sub-list for field type_name
}
func init() { file_waHistorySync_WAWebProtobufsHistorySync_proto_init() }
@@ -2656,7 +2722,7 @@ func file_waHistorySync_WAWebProtobufsHistorySync_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_waHistorySync_WAWebProtobufsHistorySync_proto_rawDesc), len(file_waHistorySync_WAWebProtobufsHistorySync_proto_rawDesc)),
NumEnums: 8,
NumMessages: 16,
NumMessages: 17,
NumExtensions: 0,
NumServices: 0,
},
@@ -135,6 +135,7 @@ message Conversation {
optional uint64 appealUpdateTime = 60;
optional string authAgentParentCompanyName = 61;
optional string authAgentObaPhoneNumber = 62;
optional IdentityVerificationState identityVerification = 63;
}
message GroupParticipant {
@@ -160,6 +161,11 @@ message PastParticipant {
optional uint64 leaveTS = 3;
}
message IdentityVerificationState {
optional bool verified = 1;
optional uint64 actionSeq = 2;
}
message PhoneNumberToLIDMapping {
optional string pnJID = 1;
optional string lidJID = 2;
@@ -1,8 +1,8 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.10
// protoc v3.21.12
// source: waServerSync/WAServerSync.proto
// protoc-gen-go v1.36.11
// protoc v7.34.1
// source: waServerSync/WAWebProtobufsServerSync.proto
package waServerSync
@@ -52,11 +52,11 @@ func (x SyncdMutation_SyncdOperation) String() string {
}
func (SyncdMutation_SyncdOperation) Descriptor() protoreflect.EnumDescriptor {
return file_waServerSync_WAServerSync_proto_enumTypes[0].Descriptor()
return file_waServerSync_WAWebProtobufsServerSync_proto_enumTypes[0].Descriptor()
}
func (SyncdMutation_SyncdOperation) Type() protoreflect.EnumType {
return &file_waServerSync_WAServerSync_proto_enumTypes[0]
return &file_waServerSync_WAWebProtobufsServerSync_proto_enumTypes[0]
}
func (x SyncdMutation_SyncdOperation) Number() protoreflect.EnumNumber {
@@ -75,12 +75,12 @@ func (x *SyncdMutation_SyncdOperation) UnmarshalJSON(b []byte) error {
// Deprecated: Use SyncdMutation_SyncdOperation.Descriptor instead.
func (SyncdMutation_SyncdOperation) EnumDescriptor() ([]byte, []int) {
return file_waServerSync_WAServerSync_proto_rawDescGZIP(), []int{0, 0}
return file_waServerSync_WAWebProtobufsServerSync_proto_rawDescGZIP(), []int{0, 0}
}
type SyncdMutation struct {
state protoimpl.MessageState `protogen:"open.v1"`
Operation *SyncdMutation_SyncdOperation `protobuf:"varint,1,opt,name=operation,enum=WAServerSync.SyncdMutation_SyncdOperation" json:"operation,omitempty"`
Operation *SyncdMutation_SyncdOperation `protobuf:"varint,1,opt,name=operation,enum=WAWebProtobufsServerSync.SyncdMutation_SyncdOperation" json:"operation,omitempty"`
Record *SyncdRecord `protobuf:"bytes,2,opt,name=record" json:"record,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
@@ -88,7 +88,7 @@ type SyncdMutation struct {
func (x *SyncdMutation) Reset() {
*x = SyncdMutation{}
mi := &file_waServerSync_WAServerSync_proto_msgTypes[0]
mi := &file_waServerSync_WAWebProtobufsServerSync_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -100,7 +100,7 @@ func (x *SyncdMutation) String() string {
func (*SyncdMutation) ProtoMessage() {}
func (x *SyncdMutation) ProtoReflect() protoreflect.Message {
mi := &file_waServerSync_WAServerSync_proto_msgTypes[0]
mi := &file_waServerSync_WAWebProtobufsServerSync_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -113,7 +113,7 @@ func (x *SyncdMutation) ProtoReflect() protoreflect.Message {
// Deprecated: Use SyncdMutation.ProtoReflect.Descriptor instead.
func (*SyncdMutation) Descriptor() ([]byte, []int) {
return file_waServerSync_WAServerSync_proto_rawDescGZIP(), []int{0}
return file_waServerSync_WAWebProtobufsServerSync_proto_rawDescGZIP(), []int{0}
}
func (x *SyncdMutation) GetOperation() SyncdMutation_SyncdOperation {
@@ -139,7 +139,7 @@ type SyncdVersion struct {
func (x *SyncdVersion) Reset() {
*x = SyncdVersion{}
mi := &file_waServerSync_WAServerSync_proto_msgTypes[1]
mi := &file_waServerSync_WAWebProtobufsServerSync_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -151,7 +151,7 @@ func (x *SyncdVersion) String() string {
func (*SyncdVersion) ProtoMessage() {}
func (x *SyncdVersion) ProtoReflect() protoreflect.Message {
mi := &file_waServerSync_WAServerSync_proto_msgTypes[1]
mi := &file_waServerSync_WAWebProtobufsServerSync_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -164,7 +164,7 @@ func (x *SyncdVersion) ProtoReflect() protoreflect.Message {
// Deprecated: Use SyncdVersion.ProtoReflect.Descriptor instead.
func (*SyncdVersion) Descriptor() ([]byte, []int) {
return file_waServerSync_WAServerSync_proto_rawDescGZIP(), []int{1}
return file_waServerSync_WAWebProtobufsServerSync_proto_rawDescGZIP(), []int{1}
}
func (x *SyncdVersion) GetVersion() uint64 {
@@ -184,7 +184,7 @@ type ExitCode struct {
func (x *ExitCode) Reset() {
*x = ExitCode{}
mi := &file_waServerSync_WAServerSync_proto_msgTypes[2]
mi := &file_waServerSync_WAWebProtobufsServerSync_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -196,7 +196,7 @@ func (x *ExitCode) String() string {
func (*ExitCode) ProtoMessage() {}
func (x *ExitCode) ProtoReflect() protoreflect.Message {
mi := &file_waServerSync_WAServerSync_proto_msgTypes[2]
mi := &file_waServerSync_WAWebProtobufsServerSync_proto_msgTypes[2]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -209,7 +209,7 @@ func (x *ExitCode) ProtoReflect() protoreflect.Message {
// Deprecated: Use ExitCode.ProtoReflect.Descriptor instead.
func (*ExitCode) Descriptor() ([]byte, []int) {
return file_waServerSync_WAServerSync_proto_rawDescGZIP(), []int{2}
return file_waServerSync_WAWebProtobufsServerSync_proto_rawDescGZIP(), []int{2}
}
func (x *ExitCode) GetCode() uint64 {
@@ -235,7 +235,7 @@ type SyncdIndex struct {
func (x *SyncdIndex) Reset() {
*x = SyncdIndex{}
mi := &file_waServerSync_WAServerSync_proto_msgTypes[3]
mi := &file_waServerSync_WAWebProtobufsServerSync_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -247,7 +247,7 @@ func (x *SyncdIndex) String() string {
func (*SyncdIndex) ProtoMessage() {}
func (x *SyncdIndex) ProtoReflect() protoreflect.Message {
mi := &file_waServerSync_WAServerSync_proto_msgTypes[3]
mi := &file_waServerSync_WAWebProtobufsServerSync_proto_msgTypes[3]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -260,7 +260,7 @@ func (x *SyncdIndex) ProtoReflect() protoreflect.Message {
// Deprecated: Use SyncdIndex.ProtoReflect.Descriptor instead.
func (*SyncdIndex) Descriptor() ([]byte, []int) {
return file_waServerSync_WAServerSync_proto_rawDescGZIP(), []int{3}
return file_waServerSync_WAWebProtobufsServerSync_proto_rawDescGZIP(), []int{3}
}
func (x *SyncdIndex) GetBlob() []byte {
@@ -279,7 +279,7 @@ type SyncdValue struct {
func (x *SyncdValue) Reset() {
*x = SyncdValue{}
mi := &file_waServerSync_WAServerSync_proto_msgTypes[4]
mi := &file_waServerSync_WAWebProtobufsServerSync_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -291,7 +291,7 @@ func (x *SyncdValue) String() string {
func (*SyncdValue) ProtoMessage() {}
func (x *SyncdValue) ProtoReflect() protoreflect.Message {
mi := &file_waServerSync_WAServerSync_proto_msgTypes[4]
mi := &file_waServerSync_WAWebProtobufsServerSync_proto_msgTypes[4]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -304,7 +304,7 @@ func (x *SyncdValue) ProtoReflect() protoreflect.Message {
// Deprecated: Use SyncdValue.ProtoReflect.Descriptor instead.
func (*SyncdValue) Descriptor() ([]byte, []int) {
return file_waServerSync_WAServerSync_proto_rawDescGZIP(), []int{4}
return file_waServerSync_WAWebProtobufsServerSync_proto_rawDescGZIP(), []int{4}
}
func (x *SyncdValue) GetBlob() []byte {
@@ -323,7 +323,7 @@ type KeyId struct {
func (x *KeyId) Reset() {
*x = KeyId{}
mi := &file_waServerSync_WAServerSync_proto_msgTypes[5]
mi := &file_waServerSync_WAWebProtobufsServerSync_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -335,7 +335,7 @@ func (x *KeyId) String() string {
func (*KeyId) ProtoMessage() {}
func (x *KeyId) ProtoReflect() protoreflect.Message {
mi := &file_waServerSync_WAServerSync_proto_msgTypes[5]
mi := &file_waServerSync_WAWebProtobufsServerSync_proto_msgTypes[5]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -348,7 +348,7 @@ func (x *KeyId) ProtoReflect() protoreflect.Message {
// Deprecated: Use KeyId.ProtoReflect.Descriptor instead.
func (*KeyId) Descriptor() ([]byte, []int) {
return file_waServerSync_WAServerSync_proto_rawDescGZIP(), []int{5}
return file_waServerSync_WAWebProtobufsServerSync_proto_rawDescGZIP(), []int{5}
}
func (x *KeyId) GetID() []byte {
@@ -369,7 +369,7 @@ type SyncdRecord struct {
func (x *SyncdRecord) Reset() {
*x = SyncdRecord{}
mi := &file_waServerSync_WAServerSync_proto_msgTypes[6]
mi := &file_waServerSync_WAWebProtobufsServerSync_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -381,7 +381,7 @@ func (x *SyncdRecord) String() string {
func (*SyncdRecord) ProtoMessage() {}
func (x *SyncdRecord) ProtoReflect() protoreflect.Message {
mi := &file_waServerSync_WAServerSync_proto_msgTypes[6]
mi := &file_waServerSync_WAWebProtobufsServerSync_proto_msgTypes[6]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -394,7 +394,7 @@ func (x *SyncdRecord) ProtoReflect() protoreflect.Message {
// Deprecated: Use SyncdRecord.ProtoReflect.Descriptor instead.
func (*SyncdRecord) Descriptor() ([]byte, []int) {
return file_waServerSync_WAServerSync_proto_rawDescGZIP(), []int{6}
return file_waServerSync_WAWebProtobufsServerSync_proto_rawDescGZIP(), []int{6}
}
func (x *SyncdRecord) GetIndex() *SyncdIndex {
@@ -432,7 +432,7 @@ type ExternalBlobReference struct {
func (x *ExternalBlobReference) Reset() {
*x = ExternalBlobReference{}
mi := &file_waServerSync_WAServerSync_proto_msgTypes[7]
mi := &file_waServerSync_WAWebProtobufsServerSync_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -444,7 +444,7 @@ func (x *ExternalBlobReference) String() string {
func (*ExternalBlobReference) ProtoMessage() {}
func (x *ExternalBlobReference) ProtoReflect() protoreflect.Message {
mi := &file_waServerSync_WAServerSync_proto_msgTypes[7]
mi := &file_waServerSync_WAWebProtobufsServerSync_proto_msgTypes[7]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -457,7 +457,7 @@ func (x *ExternalBlobReference) ProtoReflect() protoreflect.Message {
// Deprecated: Use ExternalBlobReference.ProtoReflect.Descriptor instead.
func (*ExternalBlobReference) Descriptor() ([]byte, []int) {
return file_waServerSync_WAServerSync_proto_rawDescGZIP(), []int{7}
return file_waServerSync_WAWebProtobufsServerSync_proto_rawDescGZIP(), []int{7}
}
func (x *ExternalBlobReference) GetMediaKey() []byte {
@@ -514,7 +514,7 @@ type SyncdSnapshot struct {
func (x *SyncdSnapshot) Reset() {
*x = SyncdSnapshot{}
mi := &file_waServerSync_WAServerSync_proto_msgTypes[8]
mi := &file_waServerSync_WAWebProtobufsServerSync_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -526,7 +526,7 @@ func (x *SyncdSnapshot) String() string {
func (*SyncdSnapshot) ProtoMessage() {}
func (x *SyncdSnapshot) ProtoReflect() protoreflect.Message {
mi := &file_waServerSync_WAServerSync_proto_msgTypes[8]
mi := &file_waServerSync_WAWebProtobufsServerSync_proto_msgTypes[8]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -539,7 +539,7 @@ func (x *SyncdSnapshot) ProtoReflect() protoreflect.Message {
// Deprecated: Use SyncdSnapshot.ProtoReflect.Descriptor instead.
func (*SyncdSnapshot) Descriptor() ([]byte, []int) {
return file_waServerSync_WAServerSync_proto_rawDescGZIP(), []int{8}
return file_waServerSync_WAWebProtobufsServerSync_proto_rawDescGZIP(), []int{8}
}
func (x *SyncdSnapshot) GetVersion() *SyncdVersion {
@@ -579,7 +579,7 @@ type SyncdMutations struct {
func (x *SyncdMutations) Reset() {
*x = SyncdMutations{}
mi := &file_waServerSync_WAServerSync_proto_msgTypes[9]
mi := &file_waServerSync_WAWebProtobufsServerSync_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -591,7 +591,7 @@ func (x *SyncdMutations) String() string {
func (*SyncdMutations) ProtoMessage() {}
func (x *SyncdMutations) ProtoReflect() protoreflect.Message {
mi := &file_waServerSync_WAServerSync_proto_msgTypes[9]
mi := &file_waServerSync_WAWebProtobufsServerSync_proto_msgTypes[9]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -604,7 +604,7 @@ func (x *SyncdMutations) ProtoReflect() protoreflect.Message {
// Deprecated: Use SyncdMutations.ProtoReflect.Descriptor instead.
func (*SyncdMutations) Descriptor() ([]byte, []int) {
return file_waServerSync_WAServerSync_proto_rawDescGZIP(), []int{9}
return file_waServerSync_WAWebProtobufsServerSync_proto_rawDescGZIP(), []int{9}
}
func (x *SyncdMutations) GetMutations() []*SyncdMutation {
@@ -631,7 +631,7 @@ type SyncdPatch struct {
func (x *SyncdPatch) Reset() {
*x = SyncdPatch{}
mi := &file_waServerSync_WAServerSync_proto_msgTypes[10]
mi := &file_waServerSync_WAWebProtobufsServerSync_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -643,7 +643,7 @@ func (x *SyncdPatch) String() string {
func (*SyncdPatch) ProtoMessage() {}
func (x *SyncdPatch) ProtoReflect() protoreflect.Message {
mi := &file_waServerSync_WAServerSync_proto_msgTypes[10]
mi := &file_waServerSync_WAWebProtobufsServerSync_proto_msgTypes[10]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -656,7 +656,7 @@ func (x *SyncdPatch) ProtoReflect() protoreflect.Message {
// Deprecated: Use SyncdPatch.ProtoReflect.Descriptor instead.
func (*SyncdPatch) Descriptor() ([]byte, []int) {
return file_waServerSync_WAServerSync_proto_rawDescGZIP(), []int{10}
return file_waServerSync_WAWebProtobufsServerSync_proto_rawDescGZIP(), []int{10}
}
func (x *SyncdPatch) GetVersion() *SyncdVersion {
@@ -722,14 +722,178 @@ func (x *SyncdPatch) GetClientDebugData() []byte {
return nil
}
var File_waServerSync_WAServerSync_proto protoreflect.FileDescriptor
type CoexStateSync struct {
state protoimpl.MessageState `protogen:"open.v1"`
CollectionMutations []*CoexStateSync_CollectionMutations `protobuf:"bytes,1,rep,name=collectionMutations" json:"collectionMutations,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
const file_waServerSync_WAServerSync_proto_rawDesc = "" +
func (x *CoexStateSync) Reset() {
*x = CoexStateSync{}
mi := &file_waServerSync_WAWebProtobufsServerSync_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *CoexStateSync) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CoexStateSync) ProtoMessage() {}
func (x *CoexStateSync) ProtoReflect() protoreflect.Message {
mi := &file_waServerSync_WAWebProtobufsServerSync_proto_msgTypes[11]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CoexStateSync.ProtoReflect.Descriptor instead.
func (*CoexStateSync) Descriptor() ([]byte, []int) {
return file_waServerSync_WAWebProtobufsServerSync_proto_rawDescGZIP(), []int{11}
}
func (x *CoexStateSync) GetCollectionMutations() []*CoexStateSync_CollectionMutations {
if x != nil {
return x.CollectionMutations
}
return nil
}
type CoexStateSync_CollectionMutations struct {
state protoimpl.MessageState `protogen:"open.v1"`
Collection *string `protobuf:"bytes,1,opt,name=collection" json:"collection,omitempty"`
Mutations []*CoexStateSync_Mutation `protobuf:"bytes,2,rep,name=mutations" json:"mutations,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *CoexStateSync_CollectionMutations) Reset() {
*x = CoexStateSync_CollectionMutations{}
mi := &file_waServerSync_WAWebProtobufsServerSync_proto_msgTypes[12]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *CoexStateSync_CollectionMutations) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CoexStateSync_CollectionMutations) ProtoMessage() {}
func (x *CoexStateSync_CollectionMutations) ProtoReflect() protoreflect.Message {
mi := &file_waServerSync_WAWebProtobufsServerSync_proto_msgTypes[12]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CoexStateSync_CollectionMutations.ProtoReflect.Descriptor instead.
func (*CoexStateSync_CollectionMutations) Descriptor() ([]byte, []int) {
return file_waServerSync_WAWebProtobufsServerSync_proto_rawDescGZIP(), []int{11, 0}
}
func (x *CoexStateSync_CollectionMutations) GetCollection() string {
if x != nil && x.Collection != nil {
return *x.Collection
}
return ""
}
func (x *CoexStateSync_CollectionMutations) GetMutations() []*CoexStateSync_Mutation {
if x != nil {
return x.Mutations
}
return nil
}
type CoexStateSync_Mutation struct {
state protoimpl.MessageState `protogen:"open.v1"`
Index *SyncdIndex `protobuf:"bytes,1,opt,name=index" json:"index,omitempty"`
Value *SyncdValue `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"`
DirtyVersion *uint64 `protobuf:"varint,3,opt,name=dirtyVersion" json:"dirtyVersion,omitempty"`
Operation *SyncdMutation_SyncdOperation `protobuf:"varint,4,opt,name=operation,enum=WAWebProtobufsServerSync.SyncdMutation_SyncdOperation" json:"operation,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *CoexStateSync_Mutation) Reset() {
*x = CoexStateSync_Mutation{}
mi := &file_waServerSync_WAWebProtobufsServerSync_proto_msgTypes[13]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *CoexStateSync_Mutation) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CoexStateSync_Mutation) ProtoMessage() {}
func (x *CoexStateSync_Mutation) ProtoReflect() protoreflect.Message {
mi := &file_waServerSync_WAWebProtobufsServerSync_proto_msgTypes[13]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CoexStateSync_Mutation.ProtoReflect.Descriptor instead.
func (*CoexStateSync_Mutation) Descriptor() ([]byte, []int) {
return file_waServerSync_WAWebProtobufsServerSync_proto_rawDescGZIP(), []int{11, 1}
}
func (x *CoexStateSync_Mutation) GetIndex() *SyncdIndex {
if x != nil {
return x.Index
}
return nil
}
func (x *CoexStateSync_Mutation) GetValue() *SyncdValue {
if x != nil {
return x.Value
}
return nil
}
func (x *CoexStateSync_Mutation) GetDirtyVersion() uint64 {
if x != nil && x.DirtyVersion != nil {
return *x.DirtyVersion
}
return 0
}
func (x *CoexStateSync_Mutation) GetOperation() SyncdMutation_SyncdOperation {
if x != nil && x.Operation != nil {
return *x.Operation
}
return SyncdMutation_SET
}
var File_waServerSync_WAWebProtobufsServerSync_proto protoreflect.FileDescriptor
const file_waServerSync_WAWebProtobufsServerSync_proto_rawDesc = "" +
"\n" +
"\x1fwaServerSync/WAServerSync.proto\x12\fWAServerSync\"\xb3\x01\n" +
"\rSyncdMutation\x12H\n" +
"\toperation\x18\x01 \x01(\x0e2*.WAServerSync.SyncdMutation.SyncdOperationR\toperation\x121\n" +
"\x06record\x18\x02 \x01(\v2\x19.WAServerSync.SyncdRecordR\x06record\"%\n" +
"+waServerSync/WAWebProtobufsServerSync.proto\x12\x18WAWebProtobufsServerSync\"\xcb\x01\n" +
"\rSyncdMutation\x12T\n" +
"\toperation\x18\x01 \x01(\x0e26.WAWebProtobufsServerSync.SyncdMutation.SyncdOperationR\toperation\x12=\n" +
"\x06record\x18\x02 \x01(\v2%.WAWebProtobufsServerSync.SyncdRecordR\x06record\"%\n" +
"\x0eSyncdOperation\x12\a\n" +
"\x03SET\x10\x00\x12\n" +
"\n" +
@@ -746,11 +910,11 @@ const file_waServerSync_WAServerSync_proto_rawDesc = "" +
"SyncdValue\x12\x12\n" +
"\x04blob\x18\x01 \x01(\fR\x04blob\"\x17\n" +
"\x05KeyId\x12\x0e\n" +
"\x02ID\x18\x01 \x01(\fR\x02ID\"\x98\x01\n" +
"\vSyncdRecord\x12.\n" +
"\x05index\x18\x01 \x01(\v2\x18.WAServerSync.SyncdIndexR\x05index\x12.\n" +
"\x05value\x18\x02 \x01(\v2\x18.WAServerSync.SyncdValueR\x05value\x12)\n" +
"\x05keyID\x18\x03 \x01(\v2\x13.WAServerSync.KeyIdR\x05keyID\"\xd7\x01\n" +
"\x02ID\x18\x01 \x01(\fR\x02ID\"\xbc\x01\n" +
"\vSyncdRecord\x12:\n" +
"\x05index\x18\x01 \x01(\v2$.WAWebProtobufsServerSync.SyncdIndexR\x05index\x12:\n" +
"\x05value\x18\x02 \x01(\v2$.WAWebProtobufsServerSync.SyncdValueR\x05value\x125\n" +
"\x05keyID\x18\x03 \x01(\v2\x1f.WAWebProtobufsServerSync.KeyIdR\x05keyID\"\xd7\x01\n" +
"\x15ExternalBlobReference\x12\x1a\n" +
"\bmediaKey\x18\x01 \x01(\fR\bmediaKey\x12\x1e\n" +
"\n" +
@@ -761,97 +925,117 @@ const file_waServerSync_WAServerSync_proto_rawDesc = "" +
"\n" +
"fileSHA256\x18\x05 \x01(\fR\n" +
"fileSHA256\x12$\n" +
"\rfileEncSHA256\x18\x06 \x01(\fR\rfileEncSHA256\"\xb7\x01\n" +
"\rSyncdSnapshot\x124\n" +
"\aversion\x18\x01 \x01(\v2\x1a.WAServerSync.SyncdVersionR\aversion\x123\n" +
"\arecords\x18\x02 \x03(\v2\x19.WAServerSync.SyncdRecordR\arecords\x12\x10\n" +
"\x03mac\x18\x03 \x01(\fR\x03mac\x12)\n" +
"\x05keyID\x18\x04 \x01(\v2\x13.WAServerSync.KeyIdR\x05keyID\"K\n" +
"\x0eSyncdMutations\x129\n" +
"\tmutations\x18\x01 \x03(\v2\x1b.WAServerSync.SyncdMutationR\tmutations\"\xb9\x03\n" +
"\rfileEncSHA256\x18\x06 \x01(\fR\rfileEncSHA256\"\xdb\x01\n" +
"\rSyncdSnapshot\x12@\n" +
"\aversion\x18\x01 \x01(\v2&.WAWebProtobufsServerSync.SyncdVersionR\aversion\x12?\n" +
"\arecords\x18\x02 \x03(\v2%.WAWebProtobufsServerSync.SyncdRecordR\arecords\x12\x10\n" +
"\x03mac\x18\x03 \x01(\fR\x03mac\x125\n" +
"\x05keyID\x18\x04 \x01(\v2\x1f.WAWebProtobufsServerSync.KeyIdR\x05keyID\"W\n" +
"\x0eSyncdMutations\x12E\n" +
"\tmutations\x18\x01 \x03(\v2'.WAWebProtobufsServerSync.SyncdMutationR\tmutations\"\xf5\x03\n" +
"\n" +
"SyncdPatch\x124\n" +
"\aversion\x18\x01 \x01(\v2\x1a.WAServerSync.SyncdVersionR\aversion\x129\n" +
"\tmutations\x18\x02 \x03(\v2\x1b.WAServerSync.SyncdMutationR\tmutations\x12Q\n" +
"\x11externalMutations\x18\x03 \x01(\v2#.WAServerSync.ExternalBlobReferenceR\x11externalMutations\x12 \n" +
"SyncdPatch\x12@\n" +
"\aversion\x18\x01 \x01(\v2&.WAWebProtobufsServerSync.SyncdVersionR\aversion\x12E\n" +
"\tmutations\x18\x02 \x03(\v2'.WAWebProtobufsServerSync.SyncdMutationR\tmutations\x12]\n" +
"\x11externalMutations\x18\x03 \x01(\v2/.WAWebProtobufsServerSync.ExternalBlobReferenceR\x11externalMutations\x12 \n" +
"\vsnapshotMAC\x18\x04 \x01(\fR\vsnapshotMAC\x12\x1a\n" +
"\bpatchMAC\x18\x05 \x01(\fR\bpatchMAC\x12)\n" +
"\x05keyID\x18\x06 \x01(\v2\x13.WAServerSync.KeyIdR\x05keyID\x122\n" +
"\bexitCode\x18\a \x01(\v2\x16.WAServerSync.ExitCodeR\bexitCode\x12 \n" +
"\bpatchMAC\x18\x05 \x01(\fR\bpatchMAC\x125\n" +
"\x05keyID\x18\x06 \x01(\v2\x1f.WAWebProtobufsServerSync.KeyIdR\x05keyID\x12>\n" +
"\bexitCode\x18\a \x01(\v2\".WAWebProtobufsServerSync.ExitCodeR\bexitCode\x12 \n" +
"\vdeviceIndex\x18\b \x01(\rR\vdeviceIndex\x12(\n" +
"\x0fclientDebugData\x18\t \x01(\fR\x0fclientDebugDataB(Z&go.mau.fi/whatsmeow/proto/waServerSync"
"\x0fclientDebugData\x18\t \x01(\fR\x0fclientDebugData\"\x85\x04\n" +
"\rCoexStateSync\x12m\n" +
"\x13collectionMutations\x18\x01 \x03(\v2;.WAWebProtobufsServerSync.CoexStateSync.CollectionMutationsR\x13collectionMutations\x1a\x85\x01\n" +
"\x13CollectionMutations\x12\x1e\n" +
"\n" +
"collection\x18\x01 \x01(\tR\n" +
"collection\x12N\n" +
"\tmutations\x18\x02 \x03(\v20.WAWebProtobufsServerSync.CoexStateSync.MutationR\tmutations\x1a\xfc\x01\n" +
"\bMutation\x12:\n" +
"\x05index\x18\x01 \x01(\v2$.WAWebProtobufsServerSync.SyncdIndexR\x05index\x12:\n" +
"\x05value\x18\x02 \x01(\v2$.WAWebProtobufsServerSync.SyncdValueR\x05value\x12\"\n" +
"\fdirtyVersion\x18\x03 \x01(\x04R\fdirtyVersion\x12T\n" +
"\toperation\x18\x04 \x01(\x0e26.WAWebProtobufsServerSync.SyncdMutation.SyncdOperationR\toperationB(Z&go.mau.fi/whatsmeow/proto/waServerSync"
var (
file_waServerSync_WAServerSync_proto_rawDescOnce sync.Once
file_waServerSync_WAServerSync_proto_rawDescData []byte
file_waServerSync_WAWebProtobufsServerSync_proto_rawDescOnce sync.Once
file_waServerSync_WAWebProtobufsServerSync_proto_rawDescData []byte
)
func file_waServerSync_WAServerSync_proto_rawDescGZIP() []byte {
file_waServerSync_WAServerSync_proto_rawDescOnce.Do(func() {
file_waServerSync_WAServerSync_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_waServerSync_WAServerSync_proto_rawDesc), len(file_waServerSync_WAServerSync_proto_rawDesc)))
func file_waServerSync_WAWebProtobufsServerSync_proto_rawDescGZIP() []byte {
file_waServerSync_WAWebProtobufsServerSync_proto_rawDescOnce.Do(func() {
file_waServerSync_WAWebProtobufsServerSync_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_waServerSync_WAWebProtobufsServerSync_proto_rawDesc), len(file_waServerSync_WAWebProtobufsServerSync_proto_rawDesc)))
})
return file_waServerSync_WAServerSync_proto_rawDescData
return file_waServerSync_WAWebProtobufsServerSync_proto_rawDescData
}
var file_waServerSync_WAServerSync_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_waServerSync_WAServerSync_proto_msgTypes = make([]protoimpl.MessageInfo, 11)
var file_waServerSync_WAServerSync_proto_goTypes = []any{
(SyncdMutation_SyncdOperation)(0), // 0: WAServerSync.SyncdMutation.SyncdOperation
(*SyncdMutation)(nil), // 1: WAServerSync.SyncdMutation
(*SyncdVersion)(nil), // 2: WAServerSync.SyncdVersion
(*ExitCode)(nil), // 3: WAServerSync.ExitCode
(*SyncdIndex)(nil), // 4: WAServerSync.SyncdIndex
(*SyncdValue)(nil), // 5: WAServerSync.SyncdValue
(*KeyId)(nil), // 6: WAServerSync.KeyId
(*SyncdRecord)(nil), // 7: WAServerSync.SyncdRecord
(*ExternalBlobReference)(nil), // 8: WAServerSync.ExternalBlobReference
(*SyncdSnapshot)(nil), // 9: WAServerSync.SyncdSnapshot
(*SyncdMutations)(nil), // 10: WAServerSync.SyncdMutations
(*SyncdPatch)(nil), // 11: WAServerSync.SyncdPatch
var file_waServerSync_WAWebProtobufsServerSync_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_waServerSync_WAWebProtobufsServerSync_proto_msgTypes = make([]protoimpl.MessageInfo, 14)
var file_waServerSync_WAWebProtobufsServerSync_proto_goTypes = []any{
(SyncdMutation_SyncdOperation)(0), // 0: WAWebProtobufsServerSync.SyncdMutation.SyncdOperation
(*SyncdMutation)(nil), // 1: WAWebProtobufsServerSync.SyncdMutation
(*SyncdVersion)(nil), // 2: WAWebProtobufsServerSync.SyncdVersion
(*ExitCode)(nil), // 3: WAWebProtobufsServerSync.ExitCode
(*SyncdIndex)(nil), // 4: WAWebProtobufsServerSync.SyncdIndex
(*SyncdValue)(nil), // 5: WAWebProtobufsServerSync.SyncdValue
(*KeyId)(nil), // 6: WAWebProtobufsServerSync.KeyId
(*SyncdRecord)(nil), // 7: WAWebProtobufsServerSync.SyncdRecord
(*ExternalBlobReference)(nil), // 8: WAWebProtobufsServerSync.ExternalBlobReference
(*SyncdSnapshot)(nil), // 9: WAWebProtobufsServerSync.SyncdSnapshot
(*SyncdMutations)(nil), // 10: WAWebProtobufsServerSync.SyncdMutations
(*SyncdPatch)(nil), // 11: WAWebProtobufsServerSync.SyncdPatch
(*CoexStateSync)(nil), // 12: WAWebProtobufsServerSync.CoexStateSync
(*CoexStateSync_CollectionMutations)(nil), // 13: WAWebProtobufsServerSync.CoexStateSync.CollectionMutations
(*CoexStateSync_Mutation)(nil), // 14: WAWebProtobufsServerSync.CoexStateSync.Mutation
}
var file_waServerSync_WAServerSync_proto_depIdxs = []int32{
0, // 0: WAServerSync.SyncdMutation.operation:type_name -> WAServerSync.SyncdMutation.SyncdOperation
7, // 1: WAServerSync.SyncdMutation.record:type_name -> WAServerSync.SyncdRecord
4, // 2: WAServerSync.SyncdRecord.index:type_name -> WAServerSync.SyncdIndex
5, // 3: WAServerSync.SyncdRecord.value:type_name -> WAServerSync.SyncdValue
6, // 4: WAServerSync.SyncdRecord.keyID:type_name -> WAServerSync.KeyId
2, // 5: WAServerSync.SyncdSnapshot.version:type_name -> WAServerSync.SyncdVersion
7, // 6: WAServerSync.SyncdSnapshot.records:type_name -> WAServerSync.SyncdRecord
6, // 7: WAServerSync.SyncdSnapshot.keyID:type_name -> WAServerSync.KeyId
1, // 8: WAServerSync.SyncdMutations.mutations:type_name -> WAServerSync.SyncdMutation
2, // 9: WAServerSync.SyncdPatch.version:type_name -> WAServerSync.SyncdVersion
1, // 10: WAServerSync.SyncdPatch.mutations:type_name -> WAServerSync.SyncdMutation
8, // 11: WAServerSync.SyncdPatch.externalMutations:type_name -> WAServerSync.ExternalBlobReference
6, // 12: WAServerSync.SyncdPatch.keyID:type_name -> WAServerSync.KeyId
3, // 13: WAServerSync.SyncdPatch.exitCode:type_name -> WAServerSync.ExitCode
14, // [14:14] is the sub-list for method output_type
14, // [14:14] is the sub-list for method input_type
14, // [14:14] is the sub-list for extension type_name
14, // [14:14] is the sub-list for extension extendee
0, // [0:14] is the sub-list for field type_name
var file_waServerSync_WAWebProtobufsServerSync_proto_depIdxs = []int32{
0, // 0: WAWebProtobufsServerSync.SyncdMutation.operation:type_name -> WAWebProtobufsServerSync.SyncdMutation.SyncdOperation
7, // 1: WAWebProtobufsServerSync.SyncdMutation.record:type_name -> WAWebProtobufsServerSync.SyncdRecord
4, // 2: WAWebProtobufsServerSync.SyncdRecord.index:type_name -> WAWebProtobufsServerSync.SyncdIndex
5, // 3: WAWebProtobufsServerSync.SyncdRecord.value:type_name -> WAWebProtobufsServerSync.SyncdValue
6, // 4: WAWebProtobufsServerSync.SyncdRecord.keyID:type_name -> WAWebProtobufsServerSync.KeyId
2, // 5: WAWebProtobufsServerSync.SyncdSnapshot.version:type_name -> WAWebProtobufsServerSync.SyncdVersion
7, // 6: WAWebProtobufsServerSync.SyncdSnapshot.records:type_name -> WAWebProtobufsServerSync.SyncdRecord
6, // 7: WAWebProtobufsServerSync.SyncdSnapshot.keyID:type_name -> WAWebProtobufsServerSync.KeyId
1, // 8: WAWebProtobufsServerSync.SyncdMutations.mutations:type_name -> WAWebProtobufsServerSync.SyncdMutation
2, // 9: WAWebProtobufsServerSync.SyncdPatch.version:type_name -> WAWebProtobufsServerSync.SyncdVersion
1, // 10: WAWebProtobufsServerSync.SyncdPatch.mutations:type_name -> WAWebProtobufsServerSync.SyncdMutation
8, // 11: WAWebProtobufsServerSync.SyncdPatch.externalMutations:type_name -> WAWebProtobufsServerSync.ExternalBlobReference
6, // 12: WAWebProtobufsServerSync.SyncdPatch.keyID:type_name -> WAWebProtobufsServerSync.KeyId
3, // 13: WAWebProtobufsServerSync.SyncdPatch.exitCode:type_name -> WAWebProtobufsServerSync.ExitCode
13, // 14: WAWebProtobufsServerSync.CoexStateSync.collectionMutations:type_name -> WAWebProtobufsServerSync.CoexStateSync.CollectionMutations
14, // 15: WAWebProtobufsServerSync.CoexStateSync.CollectionMutations.mutations:type_name -> WAWebProtobufsServerSync.CoexStateSync.Mutation
4, // 16: WAWebProtobufsServerSync.CoexStateSync.Mutation.index:type_name -> WAWebProtobufsServerSync.SyncdIndex
5, // 17: WAWebProtobufsServerSync.CoexStateSync.Mutation.value:type_name -> WAWebProtobufsServerSync.SyncdValue
0, // 18: WAWebProtobufsServerSync.CoexStateSync.Mutation.operation:type_name -> WAWebProtobufsServerSync.SyncdMutation.SyncdOperation
19, // [19:19] is the sub-list for method output_type
19, // [19:19] is the sub-list for method input_type
19, // [19:19] is the sub-list for extension type_name
19, // [19:19] is the sub-list for extension extendee
0, // [0:19] is the sub-list for field type_name
}
func init() { file_waServerSync_WAServerSync_proto_init() }
func file_waServerSync_WAServerSync_proto_init() {
if File_waServerSync_WAServerSync_proto != nil {
func init() { file_waServerSync_WAWebProtobufsServerSync_proto_init() }
func file_waServerSync_WAWebProtobufsServerSync_proto_init() {
if File_waServerSync_WAWebProtobufsServerSync_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_waServerSync_WAServerSync_proto_rawDesc), len(file_waServerSync_WAServerSync_proto_rawDesc)),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_waServerSync_WAWebProtobufsServerSync_proto_rawDesc), len(file_waServerSync_WAWebProtobufsServerSync_proto_rawDesc)),
NumEnums: 1,
NumMessages: 11,
NumMessages: 14,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_waServerSync_WAServerSync_proto_goTypes,
DependencyIndexes: file_waServerSync_WAServerSync_proto_depIdxs,
EnumInfos: file_waServerSync_WAServerSync_proto_enumTypes,
MessageInfos: file_waServerSync_WAServerSync_proto_msgTypes,
GoTypes: file_waServerSync_WAWebProtobufsServerSync_proto_goTypes,
DependencyIndexes: file_waServerSync_WAWebProtobufsServerSync_proto_depIdxs,
EnumInfos: file_waServerSync_WAWebProtobufsServerSync_proto_enumTypes,
MessageInfos: file_waServerSync_WAWebProtobufsServerSync_proto_msgTypes,
}.Build()
File_waServerSync_WAServerSync_proto = out.File
file_waServerSync_WAServerSync_proto_goTypes = nil
file_waServerSync_WAServerSync_proto_depIdxs = nil
File_waServerSync_WAWebProtobufsServerSync_proto = out.File
file_waServerSync_WAWebProtobufsServerSync_proto_goTypes = nil
file_waServerSync_WAWebProtobufsServerSync_proto_depIdxs = nil
}
@@ -1,5 +1,5 @@
syntax = "proto2";
package WAServerSync;
package WAWebProtobufsServerSync;
option go_package = "go.mau.fi/whatsmeow/proto/waServerSync";
message SyncdMutation {
@@ -70,3 +70,19 @@ message SyncdPatch {
optional uint32 deviceIndex = 8;
optional bytes clientDebugData = 9;
}
message CoexStateSync {
message CollectionMutations {
optional string collection = 1;
repeated Mutation mutations = 2;
}
message Mutation {
optional SyncdIndex index = 1;
optional SyncdValue value = 2;
optional uint64 dirtyVersion = 3;
optional SyncdMutation.SyncdOperation operation = 4;
}
repeated CollectionMutations collectionMutations = 1;
}
File diff suppressed because it is too large. Load diff
@@ -97,6 +97,9 @@ enum MutationProps {
THREAD_PIN_ACTION = 85;
AUTO_ORGANIZE_BUSINESS_CHAT_SETTING = 86;
BIZ_AI_SETTINGS_NUDGE_ACTION = 87;
COEX_V2_VERSION_ACTION = 88;
WASA_ROOT_SECRET_ACTION = 89;
BUBBLE_LOCK_MESSAGE_ACTION = 90;
SHARE_OWN_PN = 10001;
BUSINESS_BROADCAST_ACTION = 10002;
AI_THREAD_DELETE_ACTION = 10003;
@@ -300,6 +303,12 @@ message BizAISettingsNudgeAction {
}
message MaibaAIFeaturesControlAction {
enum MaibaAIReplyMode {
MUTED = 0;
AI_AGENT = 1;
SUGGESTIONS = 2;
}
enum MaibaAIFeatureStatus {
ENABLED = 0;
ENABLED_HAS_LEARNING = 1;
@@ -307,6 +316,7 @@ message MaibaAIFeaturesControlAction {
}
optional MaibaAIFeatureStatus aiFeatureStatus = 1;
optional MaibaAIReplyMode aiReplyMode = 2;
}
message PaymentTosAction {
@@ -383,8 +393,8 @@ message StatusPrivacyAction {
optional StatusDistributionMode mode = 1;
repeated string userJID = 2;
optional bool shareToFB = 3;
optional bool shareToIG = 4;
optional bool shareToFb = 3;
optional bool shareToIg = 4;
repeated CustomList customLists = 5;
repeated StatusDistributionMode modes = 6;
}
@@ -426,6 +436,10 @@ message LabelEditAction {
AI_HANDOFF = 9;
CHANNELS = 10;
AI_RESPONDING = 11;
ARCHIVED = 12;
LOCKED = 13;
INVITES = 14;
THIRD_PARTY = 15;
}
optional string name = 1;
@@ -551,6 +565,9 @@ enum MutationName {
THREAD_PIN_ACTION = thread_pin;
AUTO_ORGANIZE_BUSINESS_CHAT_SETTING = setting_autoOrganizeBusinessChat;
BIZ_AI_SETTINGS_NUDGE_ACTION = biz_ai_settings_nudge;
COEX_V2_VERSION_ACTION = coexV2Version;
WASA_ROOT_SECRET_ACTION = wasa_root_secret;
BUBBLE_LOCK_MESSAGE_ACTION = lock_message;
SHARE_OWN_PN = shareOwnPn;
BUSINESS_BROADCAST_ACTION = broadcast;
AI_THREAD_DELETE_ACTION = ai_thread_delete;
@@ -656,6 +673,23 @@ message SyncActionValue {
optional ThreadPinAction threadPinAction = 85;
optional AutoOrganizeBusinessChatSetting autoOrganizeBusinessChatSetting = 86;
optional BizAISettingsNudgeAction bizAiSettingsNudgeAction = 87;
optional CoexV2VersionAction coexV2VersionAction = 88;
optional WASARootSecretAction wasaRootSecretAction = 89;
optional BubbleLockMessageAction bubbleLockMessageAction = 90;
}
message WASARootSecretAction {
message RootSecretEntry {
optional string ID = 1;
optional bytes rootSecret = 2;
optional int64 epoch = 3;
}
repeated RootSecretEntry secrets = 1;
}
message CoexV2VersionAction {
optional uint64 version = 1;
}
message SubscriptionsSyncV2Action {
@@ -746,6 +780,7 @@ message BusinessBroadcastListAction {
optional string listName = 3;
repeated string labelIDs = 4;
optional string audienceExpression = 5;
optional string customAudienceFbid = 6;
}
message BusinessBroadcastAssociationAction {
@@ -787,6 +822,10 @@ message WamoUserIdentifierAction {
optional string identifier = 1;
}
message BubbleLockMessageAction {
optional bool locked = 1;
}
message LockChatAction {
optional bool locked = 1;
}
@@ -972,15 +1011,9 @@ message RecentEmojiWeightsAction {
repeated RecentEmojiWeight weights = 1;
}
message ModelMetadata {
optional string modelName = 1;
optional bool isLatestModel = 2;
optional bool isDetected = 3;
}
message LabelAssociationAction {
optional bool labeled = 1;
repeated ModelMetadata modelMetaData = 2;
optional string modelMetaData = 2;
}
message QuickReplyAction {
+212 -106
View File
@@ -316,6 +316,10 @@ const (
WebMessageInfo_GROUP_TEE_BOT_ADDED WebMessageInfo_StubType = 223
WebMessageInfo_CONTACT_INFO WebMessageInfo_StubType = 224
WebMessageInfo_SCHEDULED_MESSAGE_CREATED WebMessageInfo_StubType = 225
WebMessageInfo_IDENTITY_TRUST_MARKED WebMessageInfo_StubType = 226
WebMessageInfo_IDENTITY_TRUST_UNMARKED WebMessageInfo_StubType = 227
WebMessageInfo_IDENTITY_TRUST_REVOKED WebMessageInfo_StubType = 228
WebMessageInfo_CTWA_CONSUMER_DISCLOSURE WebMessageInfo_StubType = 230
)
// Enum value maps for WebMessageInfo_StubType.
@@ -547,6 +551,10 @@ var (
223: "GROUP_TEE_BOT_ADDED",
224: "CONTACT_INFO",
225: "SCHEDULED_MESSAGE_CREATED",
226: "IDENTITY_TRUST_MARKED",
227: "IDENTITY_TRUST_UNMARKED",
228: "IDENTITY_TRUST_REVOKED",
230: "CTWA_CONSUMER_DISCLOSURE",
}
WebMessageInfo_StubType_value = map[string]int32{
"UNKNOWN": 0,
@@ -775,6 +783,10 @@ var (
"GROUP_TEE_BOT_ADDED": 223,
"CONTACT_INFO": 224,
"SCHEDULED_MESSAGE_CREATED": 225,
"IDENTITY_TRUST_MARKED": 226,
"IDENTITY_TRUST_UNMARKED": 227,
"IDENTITY_TRUST_REVOKED": 228,
"CTWA_CONSUMER_DISCLOSURE": 230,
}
)
@@ -1365,6 +1377,7 @@ const (
GroupHistoryBundleInfo_INJECTED_PARTIAL GroupHistoryBundleInfo_ProcessState = 2
GroupHistoryBundleInfo_INJECTION_FAILED GroupHistoryBundleInfo_ProcessState = 3
GroupHistoryBundleInfo_INJECTION_FAILED_NO_RETRY GroupHistoryBundleInfo_ProcessState = 4
GroupHistoryBundleInfo_DEDUPED GroupHistoryBundleInfo_ProcessState = 5
)
// Enum value maps for GroupHistoryBundleInfo_ProcessState.
@@ -1375,6 +1388,7 @@ var (
2: "INJECTED_PARTIAL",
3: "INJECTION_FAILED",
4: "INJECTION_FAILED_NO_RETRY",
5: "DEDUPED",
}
GroupHistoryBundleInfo_ProcessState_value = map[string]int32{
"NOT_INJECTED": 0,
@@ -1382,6 +1396,7 @@ var (
"INJECTED_PARTIAL": 2,
"INJECTION_FAILED": 3,
"INJECTION_FAILED_NO_RETRY": 4,
"DEDUPED": 5,
}
)
@@ -2987,10 +3002,11 @@ func (x *NotificationMessageInfo) GetParticipant() string {
}
type ReportingTokenInfo struct {
state protoimpl.MessageState `protogen:"open.v1"`
ReportingTag []byte `protobuf:"bytes,1,opt,name=reportingTag" json:"reportingTag,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
ReportingTag []byte `protobuf:"bytes,1,opt,name=reportingTag" json:"reportingTag,omitempty"`
ReportingTagTimestamp *uint64 `protobuf:"varint,2,opt,name=reportingTagTimestamp" json:"reportingTagTimestamp,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ReportingTokenInfo) Reset() {
@@ -3030,6 +3046,13 @@ func (x *ReportingTokenInfo) GetReportingTag() []byte {
return nil
}
func (x *ReportingTokenInfo) GetReportingTagTimestamp() uint64 {
if x != nil && x.ReportingTagTimestamp != nil {
return *x.ReportingTagTimestamp
}
return 0
}
type MediaData struct {
state protoimpl.MessageState `protogen:"open.v1"`
LocalPath *string `protobuf:"bytes,1,opt,name=localPath" json:"localPath,omitempty"`
@@ -3347,12 +3370,13 @@ func (x *Reaction) GetUnread() bool {
}
type PollUpdate struct {
state protoimpl.MessageState `protogen:"open.v1"`
PollUpdateMessageKey *waCommon.MessageKey `protobuf:"bytes,1,opt,name=pollUpdateMessageKey" json:"pollUpdateMessageKey,omitempty"`
Vote *waE2E.PollVoteMessage `protobuf:"bytes,2,opt,name=vote" json:"vote,omitempty"`
SenderTimestampMS *int64 `protobuf:"varint,3,opt,name=senderTimestampMS" json:"senderTimestampMS,omitempty"`
ServerTimestampMS *int64 `protobuf:"varint,4,opt,name=serverTimestampMS" json:"serverTimestampMS,omitempty"`
Unread *bool `protobuf:"varint,5,opt,name=unread" json:"unread,omitempty"`
state protoimpl.MessageState `protogen:"open.v1"`
PollUpdateMessageKey *waCommon.MessageKey `protobuf:"bytes,1,opt,name=pollUpdateMessageKey" json:"pollUpdateMessageKey,omitempty"`
Vote *waE2E.PollVoteMessage `protobuf:"bytes,2,opt,name=vote" json:"vote,omitempty"`
SenderTimestampMS *int64 `protobuf:"varint,3,opt,name=senderTimestampMS" json:"senderTimestampMS,omitempty"`
ServerTimestampMS *int64 `protobuf:"varint,4,opt,name=serverTimestampMS" json:"serverTimestampMS,omitempty"`
Unread *bool `protobuf:"varint,5,opt,name=unread" json:"unread,omitempty"`
Metadata *waE2E.PollUpdateMessageMetadata `protobuf:"bytes,6,opt,name=metadata" json:"metadata,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
@@ -3422,11 +3446,19 @@ func (x *PollUpdate) GetUnread() bool {
return false
}
func (x *PollUpdate) GetMetadata() *waE2E.PollUpdateMessageMetadata {
if x != nil {
return x.Metadata
}
return nil
}
type PollAdditionalMetadata struct {
state protoimpl.MessageState `protogen:"open.v1"`
PollInvalidated *bool `protobuf:"varint,1,opt,name=pollInvalidated" json:"pollInvalidated,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
PollInvalidated *bool `protobuf:"varint,1,opt,name=pollInvalidated" json:"pollInvalidated,omitempty"`
PollNameHashHistory []*PollAdditionalMetadata_PollNameHashHistoryEntry `protobuf:"bytes,2,rep,name=pollNameHashHistory" json:"pollNameHashHistory,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *PollAdditionalMetadata) Reset() {
@@ -3466,6 +3498,13 @@ func (x *PollAdditionalMetadata) GetPollInvalidated() bool {
return false
}
func (x *PollAdditionalMetadata) GetPollNameHashHistory() []*PollAdditionalMetadata_PollNameHashHistoryEntry {
if x != nil {
return x.PollNameHashHistory
}
return nil
}
type InteractiveMessageAdditionalMetadata struct {
state protoimpl.MessageState `protogen:"open.v1"`
IsGalaxyFlowCompleted *bool `protobuf:"varint,1,opt,name=isGalaxyFlowCompleted" json:"isGalaxyFlowCompleted,omitempty"`
@@ -4130,11 +4169,63 @@ func (x *ScheduledMessageMetadata) GetScheduledTime() uint64 {
return 0
}
type PollAdditionalMetadata_PollNameHashHistoryEntry struct {
state protoimpl.MessageState `protogen:"open.v1"`
EditStanzaID *string `protobuf:"bytes,1,opt,name=editStanzaID" json:"editStanzaID,omitempty"`
PollNameHash []byte `protobuf:"bytes,2,opt,name=pollNameHash" json:"pollNameHash,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *PollAdditionalMetadata_PollNameHashHistoryEntry) Reset() {
*x = PollAdditionalMetadata_PollNameHashHistoryEntry{}
mi := &file_waWeb_WAWebProtobufsWeb_proto_msgTypes[29]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *PollAdditionalMetadata_PollNameHashHistoryEntry) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*PollAdditionalMetadata_PollNameHashHistoryEntry) ProtoMessage() {}
func (x *PollAdditionalMetadata_PollNameHashHistoryEntry) ProtoReflect() protoreflect.Message {
mi := &file_waWeb_WAWebProtobufsWeb_proto_msgTypes[29]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use PollAdditionalMetadata_PollNameHashHistoryEntry.ProtoReflect.Descriptor instead.
func (*PollAdditionalMetadata_PollNameHashHistoryEntry) Descriptor() ([]byte, []int) {
return file_waWeb_WAWebProtobufsWeb_proto_rawDescGZIP(), []int{16, 0}
}
func (x *PollAdditionalMetadata_PollNameHashHistoryEntry) GetEditStanzaID() string {
if x != nil && x.EditStanzaID != nil {
return *x.EditStanzaID
}
return ""
}
func (x *PollAdditionalMetadata_PollNameHashHistoryEntry) GetPollNameHash() []byte {
if x != nil {
return x.PollNameHash
}
return nil
}
var File_waWeb_WAWebProtobufsWeb_proto protoreflect.FileDescriptor
const file_waWeb_WAWebProtobufsWeb_proto_rawDesc = "" +
"\n" +
"\x1dwaWeb/WAWebProtobufsWeb.proto\x12\x11WAWebProtobufsWeb\x1a\x1dwaE2E/WAWebProtobufsE2E.proto\x1a\x17waCommon/WACommon.proto\"\xac^\n" +
"\x1dwaWeb/WAWebProtobufsWeb.proto\x12\x11WAWebProtobufsWeb\x1a\x1dwaE2E/WAWebProtobufsE2E.proto\x1a\x17waCommon/WACommon.proto\"\xa2_\n" +
"\x0eWebMessageInfo\x12&\n" +
"\x03key\x18\x01 \x02(\v2\x14.WACommon.MessageKeyR\x03key\x124\n" +
"\amessage\x18\x02 \x01(\v2\x1a.WAWebProtobufsE2E.MessageR\amessage\x12*\n" +
@@ -4219,7 +4310,7 @@ const file_waWeb_WAWebProtobufsWeb_proto_rawDesc = "" +
"\x02FB\x10\x02\x12\a\n" +
"\x03BSP\x10\x01\x12\x0e\n" +
"\n" +
"BSP_AND_FB\x10\x03\"\x83<\n" +
"BSP_AND_FB\x10\x03\"\xf9<\n" +
"\bStubType\x12\v\n" +
"\aUNKNOWN\x10\x00\x12\n" +
"\n" +
@@ -4450,7 +4541,11 @@ const file_waWeb_WAWebProtobufsWeb_proto_rawDesc = "" +
"\x14GROUP_OPEN_BOT_ADDED\x10\xde\x01\x12\x18\n" +
"\x13GROUP_TEE_BOT_ADDED\x10\xdf\x01\x12\x11\n" +
"\fCONTACT_INFO\x10\xe0\x01\x12\x1e\n" +
"\x19SCHEDULED_MESSAGE_CREATED\x10\xe1\x01\"X\n" +
"\x19SCHEDULED_MESSAGE_CREATED\x10\xe1\x01\x12\x1a\n" +
"\x15IDENTITY_TRUST_MARKED\x10\xe2\x01\x12\x1c\n" +
"\x17IDENTITY_TRUST_UNMARKED\x10\xe3\x01\x12\x1b\n" +
"\x16IDENTITY_TRUST_REVOKED\x10\xe4\x01\x12\x1d\n" +
"\x18CTWA_CONSUMER_DISCLOSURE\x10\xe6\x01\"X\n" +
"\x06Status\x12\t\n" +
"\x05ERROR\x10\x00\x12\v\n" +
"\aPENDING\x10\x01\x12\x0e\n" +
@@ -4613,16 +4708,17 @@ const file_waWeb_WAWebProtobufsWeb_proto_rawDesc = "" +
"\bREACTION\x10\x01\x12\x12\n" +
"\x0eEVENT_RESPONSE\x10\x02\x12\x0f\n" +
"\vPOLL_UPDATE\x10\x03\x12\x0f\n" +
"\vPIN_IN_CHAT\x10\x04\"\xe0\x02\n" +
"\vPIN_IN_CHAT\x10\x04\"\xee\x02\n" +
"\x16GroupHistoryBundleInfo\x12o\n" +
"\x1edeprecatedMessageHistoryBundle\x18\x01 \x01(\v2'.WAWebProtobufsE2E.MessageHistoryBundleR\x1edeprecatedMessageHistoryBundle\x12Z\n" +
"\fprocessState\x18\x02 \x01(\x0e26.WAWebProtobufsWeb.GroupHistoryBundleInfo.ProcessStateR\fprocessState\"y\n" +
"\fprocessState\x18\x02 \x01(\x0e26.WAWebProtobufsWeb.GroupHistoryBundleInfo.ProcessStateR\fprocessState\"\x86\x01\n" +
"\fProcessState\x12\x10\n" +
"\fNOT_INJECTED\x10\x00\x12\f\n" +
"\bINJECTED\x10\x01\x12\x14\n" +
"\x10INJECTED_PARTIAL\x10\x02\x12\x14\n" +
"\x10INJECTION_FAILED\x10\x03\x12\x1d\n" +
"\x19INJECTION_FAILED_NO_RETRY\x10\x04\"s\n" +
"\x19INJECTION_FAILED_NO_RETRY\x10\x04\x12\v\n" +
"\aDEDUPED\x10\x05\"s\n" +
"\x0fCommentMetadata\x12@\n" +
"\x10commentParentKey\x18\x01 \x01(\v2\x14.WACommon.MessageKeyR\x10commentParentKey\x12\x1e\n" +
"\n" +
@@ -4637,9 +4733,10 @@ const file_waWeb_WAWebProtobufsWeb_proto_rawDesc = "" +
"\x03key\x18\x01 \x01(\v2\x14.WACommon.MessageKeyR\x03key\x124\n" +
"\amessage\x18\x02 \x01(\v2\x1a.WAWebProtobufsE2E.MessageR\amessage\x12*\n" +
"\x10messageTimestamp\x18\x03 \x01(\x04R\x10messageTimestamp\x12 \n" +
"\vparticipant\x18\x04 \x01(\tR\vparticipant\"8\n" +
"\vparticipant\x18\x04 \x01(\tR\vparticipant\"n\n" +
"\x12ReportingTokenInfo\x12\"\n" +
"\freportingTag\x18\x01 \x01(\fR\freportingTag\")\n" +
"\freportingTag\x18\x01 \x01(\fR\freportingTag\x124\n" +
"\x15reportingTagTimestamp\x18\x02 \x01(\x04R\x15reportingTagTimestamp\")\n" +
"\tMediaData\x12\x1c\n" +
"\tlocalPath\x18\x01 \x01(\tR\tlocalPath\"e\n" +
"\vPhotoChange\x12\x1a\n" +
@@ -4665,16 +4762,21 @@ const file_waWeb_WAWebProtobufsWeb_proto_rawDesc = "" +
"\x04text\x18\x02 \x01(\tR\x04text\x12 \n" +
"\vgroupingKey\x18\x03 \x01(\tR\vgroupingKey\x12,\n" +
"\x11senderTimestampMS\x18\x04 \x01(\x03R\x11senderTimestampMS\x12\x16\n" +
"\x06unread\x18\x05 \x01(\bR\x06unread\"\x82\x02\n" +
"\x06unread\x18\x05 \x01(\bR\x06unread\"\xcc\x02\n" +
"\n" +
"PollUpdate\x12H\n" +
"\x14pollUpdateMessageKey\x18\x01 \x01(\v2\x14.WACommon.MessageKeyR\x14pollUpdateMessageKey\x126\n" +
"\x04vote\x18\x02 \x01(\v2\".WAWebProtobufsE2E.PollVoteMessageR\x04vote\x12,\n" +
"\x11senderTimestampMS\x18\x03 \x01(\x03R\x11senderTimestampMS\x12,\n" +
"\x11serverTimestampMS\x18\x04 \x01(\x03R\x11serverTimestampMS\x12\x16\n" +
"\x06unread\x18\x05 \x01(\bR\x06unread\"B\n" +
"\x06unread\x18\x05 \x01(\bR\x06unread\x12H\n" +
"\bmetadata\x18\x06 \x01(\v2,.WAWebProtobufsE2E.PollUpdateMessageMetadataR\bmetadata\"\x9c\x02\n" +
"\x16PollAdditionalMetadata\x12(\n" +
"\x0fpollInvalidated\x18\x01 \x01(\bR\x0fpollInvalidated\"\\\n" +
"\x0fpollInvalidated\x18\x01 \x01(\bR\x0fpollInvalidated\x12t\n" +
"\x13pollNameHashHistory\x18\x02 \x03(\v2B.WAWebProtobufsWeb.PollAdditionalMetadata.PollNameHashHistoryEntryR\x13pollNameHashHistory\x1ab\n" +
"\x18PollNameHashHistoryEntry\x12\"\n" +
"\feditStanzaID\x18\x01 \x01(\tR\feditStanzaID\x12\"\n" +
"\fpollNameHash\x18\x02 \x01(\fR\fpollNameHash\"\\\n" +
"$InteractiveMessageAdditionalMetadata\x124\n" +
"\x15isGalaxyFlowCompleted\x18\x01 \x01(\bR\x15isGalaxyFlowCompleted\"3\n" +
"\x17EventAdditionalMetadata\x12\x18\n" +
@@ -4731,64 +4833,66 @@ func file_waWeb_WAWebProtobufsWeb_proto_rawDescGZIP() []byte {
}
var file_waWeb_WAWebProtobufsWeb_proto_enumTypes = make([]protoimpl.EnumInfo, 10)
var file_waWeb_WAWebProtobufsWeb_proto_msgTypes = make([]protoimpl.MessageInfo, 29)
var file_waWeb_WAWebProtobufsWeb_proto_msgTypes = make([]protoimpl.MessageInfo, 30)
var file_waWeb_WAWebProtobufsWeb_proto_goTypes = []any{
(WebMessageInfo_BizPrivacyStatus)(0), // 0: WAWebProtobufsWeb.WebMessageInfo.BizPrivacyStatus
(WebMessageInfo_StubType)(0), // 1: WAWebProtobufsWeb.WebMessageInfo.StubType
(WebMessageInfo_Status)(0), // 2: WAWebProtobufsWeb.WebMessageInfo.Status
(PaymentInfo_TxnStatus)(0), // 3: WAWebProtobufsWeb.PaymentInfo.TxnStatus
(PaymentInfo_Status)(0), // 4: WAWebProtobufsWeb.PaymentInfo.Status
(PaymentInfo_Currency)(0), // 5: WAWebProtobufsWeb.PaymentInfo.Currency
(WebFeatures_Flag)(0), // 6: WAWebProtobufsWeb.WebFeatures.Flag
(PinInChat_Type)(0), // 7: WAWebProtobufsWeb.PinInChat.Type
(MessageAddOn_MessageAddOnType)(0), // 8: WAWebProtobufsWeb.MessageAddOn.MessageAddOnType
(GroupHistoryBundleInfo_ProcessState)(0), // 9: WAWebProtobufsWeb.GroupHistoryBundleInfo.ProcessState
(*WebMessageInfo)(nil), // 10: WAWebProtobufsWeb.WebMessageInfo
(*PaymentInfo)(nil), // 11: WAWebProtobufsWeb.PaymentInfo
(*WebFeatures)(nil), // 12: WAWebProtobufsWeb.WebFeatures
(*PinInChat)(nil), // 13: WAWebProtobufsWeb.PinInChat
(*MessageAddOn)(nil), // 14: WAWebProtobufsWeb.MessageAddOn
(*GroupHistoryBundleInfo)(nil), // 15: WAWebProtobufsWeb.GroupHistoryBundleInfo
(*CommentMetadata)(nil), // 16: WAWebProtobufsWeb.CommentMetadata
(*WebNotificationsInfo)(nil), // 17: WAWebProtobufsWeb.WebNotificationsInfo
(*NotificationMessageInfo)(nil), // 18: WAWebProtobufsWeb.NotificationMessageInfo
(*ReportingTokenInfo)(nil), // 19: WAWebProtobufsWeb.ReportingTokenInfo
(*MediaData)(nil), // 20: WAWebProtobufsWeb.MediaData
(*PhotoChange)(nil), // 21: WAWebProtobufsWeb.PhotoChange
(*StatusPSA)(nil), // 22: WAWebProtobufsWeb.StatusPSA
(*UserReceipt)(nil), // 23: WAWebProtobufsWeb.UserReceipt
(*Reaction)(nil), // 24: WAWebProtobufsWeb.Reaction
(*PollUpdate)(nil), // 25: WAWebProtobufsWeb.PollUpdate
(*PollAdditionalMetadata)(nil), // 26: WAWebProtobufsWeb.PollAdditionalMetadata
(*InteractiveMessageAdditionalMetadata)(nil), // 27: WAWebProtobufsWeb.InteractiveMessageAdditionalMetadata
(*EventAdditionalMetadata)(nil), // 28: WAWebProtobufsWeb.EventAdditionalMetadata
(*KeepInChat)(nil), // 29: WAWebProtobufsWeb.KeepInChat
(*MessageAddOnContextInfo)(nil), // 30: WAWebProtobufsWeb.MessageAddOnContextInfo
(*PremiumMessageInfo)(nil), // 31: WAWebProtobufsWeb.PremiumMessageInfo
(*EventResponse)(nil), // 32: WAWebProtobufsWeb.EventResponse
(*LegacyMessage)(nil), // 33: WAWebProtobufsWeb.LegacyMessage
(*StatusMentionMessage)(nil), // 34: WAWebProtobufsWeb.StatusMentionMessage
(*Citation)(nil), // 35: WAWebProtobufsWeb.Citation
(*GroupHistoryIndividualMessageInfo)(nil), // 36: WAWebProtobufsWeb.GroupHistoryIndividualMessageInfo
(*QuarantinedMessage)(nil), // 37: WAWebProtobufsWeb.QuarantinedMessage
(*ScheduledMessageMetadata)(nil), // 38: WAWebProtobufsWeb.ScheduledMessageMetadata
(*waCommon.MessageKey)(nil), // 39: WACommon.MessageKey
(*waE2E.Message)(nil), // 40: WAWebProtobufsE2E.Message
(*waE2E.LiveLocationMessage)(nil), // 41: WAWebProtobufsE2E.LiveLocationMessage
(*waE2E.Money)(nil), // 42: WAWebProtobufsE2E.Money
(*waE2E.MessageHistoryBundle)(nil), // 43: WAWebProtobufsE2E.MessageHistoryBundle
(*waE2E.PollVoteMessage)(nil), // 44: WAWebProtobufsE2E.PollVoteMessage
(waE2E.KeepType)(0), // 45: WAWebProtobufsE2E.KeepType
(waE2E.MessageContextInfo_MessageAddonExpiryType)(0), // 46: WAWebProtobufsE2E.MessageContextInfo.MessageAddonExpiryType
(*waE2E.EventResponseMessage)(nil), // 47: WAWebProtobufsE2E.EventResponseMessage
(WebMessageInfo_BizPrivacyStatus)(0), // 0: WAWebProtobufsWeb.WebMessageInfo.BizPrivacyStatus
(WebMessageInfo_StubType)(0), // 1: WAWebProtobufsWeb.WebMessageInfo.StubType
(WebMessageInfo_Status)(0), // 2: WAWebProtobufsWeb.WebMessageInfo.Status
(PaymentInfo_TxnStatus)(0), // 3: WAWebProtobufsWeb.PaymentInfo.TxnStatus
(PaymentInfo_Status)(0), // 4: WAWebProtobufsWeb.PaymentInfo.Status
(PaymentInfo_Currency)(0), // 5: WAWebProtobufsWeb.PaymentInfo.Currency
(WebFeatures_Flag)(0), // 6: WAWebProtobufsWeb.WebFeatures.Flag
(PinInChat_Type)(0), // 7: WAWebProtobufsWeb.PinInChat.Type
(MessageAddOn_MessageAddOnType)(0), // 8: WAWebProtobufsWeb.MessageAddOn.MessageAddOnType
(GroupHistoryBundleInfo_ProcessState)(0), // 9: WAWebProtobufsWeb.GroupHistoryBundleInfo.ProcessState
(*WebMessageInfo)(nil), // 10: WAWebProtobufsWeb.WebMessageInfo
(*PaymentInfo)(nil), // 11: WAWebProtobufsWeb.PaymentInfo
(*WebFeatures)(nil), // 12: WAWebProtobufsWeb.WebFeatures
(*PinInChat)(nil), // 13: WAWebProtobufsWeb.PinInChat
(*MessageAddOn)(nil), // 14: WAWebProtobufsWeb.MessageAddOn
(*GroupHistoryBundleInfo)(nil), // 15: WAWebProtobufsWeb.GroupHistoryBundleInfo
(*CommentMetadata)(nil), // 16: WAWebProtobufsWeb.CommentMetadata
(*WebNotificationsInfo)(nil), // 17: WAWebProtobufsWeb.WebNotificationsInfo
(*NotificationMessageInfo)(nil), // 18: WAWebProtobufsWeb.NotificationMessageInfo
(*ReportingTokenInfo)(nil), // 19: WAWebProtobufsWeb.ReportingTokenInfo
(*MediaData)(nil), // 20: WAWebProtobufsWeb.MediaData
(*PhotoChange)(nil), // 21: WAWebProtobufsWeb.PhotoChange
(*StatusPSA)(nil), // 22: WAWebProtobufsWeb.StatusPSA
(*UserReceipt)(nil), // 23: WAWebProtobufsWeb.UserReceipt
(*Reaction)(nil), // 24: WAWebProtobufsWeb.Reaction
(*PollUpdate)(nil), // 25: WAWebProtobufsWeb.PollUpdate
(*PollAdditionalMetadata)(nil), // 26: WAWebProtobufsWeb.PollAdditionalMetadata
(*InteractiveMessageAdditionalMetadata)(nil), // 27: WAWebProtobufsWeb.InteractiveMessageAdditionalMetadata
(*EventAdditionalMetadata)(nil), // 28: WAWebProtobufsWeb.EventAdditionalMetadata
(*KeepInChat)(nil), // 29: WAWebProtobufsWeb.KeepInChat
(*MessageAddOnContextInfo)(nil), // 30: WAWebProtobufsWeb.MessageAddOnContextInfo
(*PremiumMessageInfo)(nil), // 31: WAWebProtobufsWeb.PremiumMessageInfo
(*EventResponse)(nil), // 32: WAWebProtobufsWeb.EventResponse
(*LegacyMessage)(nil), // 33: WAWebProtobufsWeb.LegacyMessage
(*StatusMentionMessage)(nil), // 34: WAWebProtobufsWeb.StatusMentionMessage
(*Citation)(nil), // 35: WAWebProtobufsWeb.Citation
(*GroupHistoryIndividualMessageInfo)(nil), // 36: WAWebProtobufsWeb.GroupHistoryIndividualMessageInfo
(*QuarantinedMessage)(nil), // 37: WAWebProtobufsWeb.QuarantinedMessage
(*ScheduledMessageMetadata)(nil), // 38: WAWebProtobufsWeb.ScheduledMessageMetadata
(*PollAdditionalMetadata_PollNameHashHistoryEntry)(nil), // 39: WAWebProtobufsWeb.PollAdditionalMetadata.PollNameHashHistoryEntry
(*waCommon.MessageKey)(nil), // 40: WACommon.MessageKey
(*waE2E.Message)(nil), // 41: WAWebProtobufsE2E.Message
(*waE2E.LiveLocationMessage)(nil), // 42: WAWebProtobufsE2E.LiveLocationMessage
(*waE2E.Money)(nil), // 43: WAWebProtobufsE2E.Money
(*waE2E.MessageHistoryBundle)(nil), // 44: WAWebProtobufsE2E.MessageHistoryBundle
(*waE2E.PollVoteMessage)(nil), // 45: WAWebProtobufsE2E.PollVoteMessage
(*waE2E.PollUpdateMessageMetadata)(nil), // 46: WAWebProtobufsE2E.PollUpdateMessageMetadata
(waE2E.KeepType)(0), // 47: WAWebProtobufsE2E.KeepType
(waE2E.MessageContextInfo_MessageAddonExpiryType)(0), // 48: WAWebProtobufsE2E.MessageContextInfo.MessageAddonExpiryType
(*waE2E.EventResponseMessage)(nil), // 49: WAWebProtobufsE2E.EventResponseMessage
}
var file_waWeb_WAWebProtobufsWeb_proto_depIdxs = []int32{
39, // 0: WAWebProtobufsWeb.WebMessageInfo.key:type_name -> WACommon.MessageKey
40, // 1: WAWebProtobufsWeb.WebMessageInfo.message:type_name -> WAWebProtobufsE2E.Message
40, // 0: WAWebProtobufsWeb.WebMessageInfo.key:type_name -> WACommon.MessageKey
41, // 1: WAWebProtobufsWeb.WebMessageInfo.message:type_name -> WAWebProtobufsE2E.Message
2, // 2: WAWebProtobufsWeb.WebMessageInfo.status:type_name -> WAWebProtobufsWeb.WebMessageInfo.Status
1, // 3: WAWebProtobufsWeb.WebMessageInfo.messageStubType:type_name -> WAWebProtobufsWeb.WebMessageInfo.StubType
11, // 4: WAWebProtobufsWeb.WebMessageInfo.paymentInfo:type_name -> WAWebProtobufsWeb.PaymentInfo
41, // 5: WAWebProtobufsWeb.WebMessageInfo.finalLiveLocation:type_name -> WAWebProtobufsE2E.LiveLocationMessage
42, // 5: WAWebProtobufsWeb.WebMessageInfo.finalLiveLocation:type_name -> WAWebProtobufsE2E.LiveLocationMessage
11, // 6: WAWebProtobufsWeb.WebMessageInfo.quotedPaymentInfo:type_name -> WAWebProtobufsWeb.PaymentInfo
0, // 7: WAWebProtobufsWeb.WebMessageInfo.bizPrivacyStatus:type_name -> WAWebProtobufsWeb.WebMessageInfo.BizPrivacyStatus
20, // 8: WAWebProtobufsWeb.WebMessageInfo.mediaData:type_name -> WAWebProtobufsWeb.MediaData
@@ -4806,7 +4910,7 @@ var file_waWeb_WAWebProtobufsWeb_proto_depIdxs = []int32{
32, // 20: WAWebProtobufsWeb.WebMessageInfo.eventResponses:type_name -> WAWebProtobufsWeb.EventResponse
19, // 21: WAWebProtobufsWeb.WebMessageInfo.reportingTokenInfo:type_name -> WAWebProtobufsWeb.ReportingTokenInfo
28, // 22: WAWebProtobufsWeb.WebMessageInfo.eventAdditionalMetadata:type_name -> WAWebProtobufsWeb.EventAdditionalMetadata
39, // 23: WAWebProtobufsWeb.WebMessageInfo.targetMessageID:type_name -> WACommon.MessageKey
40, // 23: WAWebProtobufsWeb.WebMessageInfo.targetMessageID:type_name -> WACommon.MessageKey
14, // 24: WAWebProtobufsWeb.WebMessageInfo.messageAddOns:type_name -> WAWebProtobufsWeb.MessageAddOn
34, // 25: WAWebProtobufsWeb.WebMessageInfo.statusMentionMessageInfo:type_name -> WAWebProtobufsWeb.StatusMentionMessage
35, // 26: WAWebProtobufsWeb.WebMessageInfo.supportAiCitations:type_name -> WAWebProtobufsWeb.Citation
@@ -4817,10 +4921,10 @@ var file_waWeb_WAWebProtobufsWeb_proto_depIdxs = []int32{
38, // 31: WAWebProtobufsWeb.WebMessageInfo.scheduledMessageMetadata:type_name -> WAWebProtobufsWeb.ScheduledMessageMetadata
5, // 32: WAWebProtobufsWeb.PaymentInfo.currencyDeprecated:type_name -> WAWebProtobufsWeb.PaymentInfo.Currency
4, // 33: WAWebProtobufsWeb.PaymentInfo.status:type_name -> WAWebProtobufsWeb.PaymentInfo.Status
39, // 34: WAWebProtobufsWeb.PaymentInfo.requestMessageKey:type_name -> WACommon.MessageKey
40, // 34: WAWebProtobufsWeb.PaymentInfo.requestMessageKey:type_name -> WACommon.MessageKey
3, // 35: WAWebProtobufsWeb.PaymentInfo.txnStatus:type_name -> WAWebProtobufsWeb.PaymentInfo.TxnStatus
42, // 36: WAWebProtobufsWeb.PaymentInfo.primaryAmount:type_name -> WAWebProtobufsE2E.Money
42, // 37: WAWebProtobufsWeb.PaymentInfo.exchangeAmount:type_name -> WAWebProtobufsE2E.Money
43, // 36: WAWebProtobufsWeb.PaymentInfo.primaryAmount:type_name -> WAWebProtobufsE2E.Money
43, // 37: WAWebProtobufsWeb.PaymentInfo.exchangeAmount:type_name -> WAWebProtobufsE2E.Money
6, // 38: WAWebProtobufsWeb.WebFeatures.labelsDisplay:type_name -> WAWebProtobufsWeb.WebFeatures.Flag
6, // 39: WAWebProtobufsWeb.WebFeatures.voipIndividualOutgoing:type_name -> WAWebProtobufsWeb.WebFeatures.Flag
6, // 40: WAWebProtobufsWeb.WebFeatures.groupsV3:type_name -> WAWebProtobufsWeb.WebFeatures.Flag
@@ -4867,37 +4971,39 @@ var file_waWeb_WAWebProtobufsWeb_proto_depIdxs = []int32{
6, // 81: WAWebProtobufsWeb.WebFeatures.externalMdOptInAvailable:type_name -> WAWebProtobufsWeb.WebFeatures.Flag
6, // 82: WAWebProtobufsWeb.WebFeatures.noDeleteMessageTimeLimit:type_name -> WAWebProtobufsWeb.WebFeatures.Flag
7, // 83: WAWebProtobufsWeb.PinInChat.type:type_name -> WAWebProtobufsWeb.PinInChat.Type
39, // 84: WAWebProtobufsWeb.PinInChat.key:type_name -> WACommon.MessageKey
40, // 84: WAWebProtobufsWeb.PinInChat.key:type_name -> WACommon.MessageKey
30, // 85: WAWebProtobufsWeb.PinInChat.messageAddOnContextInfo:type_name -> WAWebProtobufsWeb.MessageAddOnContextInfo
8, // 86: WAWebProtobufsWeb.MessageAddOn.messageAddOnType:type_name -> WAWebProtobufsWeb.MessageAddOn.MessageAddOnType
40, // 87: WAWebProtobufsWeb.MessageAddOn.messageAddOn:type_name -> WAWebProtobufsE2E.Message
41, // 87: WAWebProtobufsWeb.MessageAddOn.messageAddOn:type_name -> WAWebProtobufsE2E.Message
2, // 88: WAWebProtobufsWeb.MessageAddOn.status:type_name -> WAWebProtobufsWeb.WebMessageInfo.Status
30, // 89: WAWebProtobufsWeb.MessageAddOn.addOnContextInfo:type_name -> WAWebProtobufsWeb.MessageAddOnContextInfo
39, // 90: WAWebProtobufsWeb.MessageAddOn.messageAddOnKey:type_name -> WACommon.MessageKey
40, // 90: WAWebProtobufsWeb.MessageAddOn.messageAddOnKey:type_name -> WACommon.MessageKey
33, // 91: WAWebProtobufsWeb.MessageAddOn.legacyMessage:type_name -> WAWebProtobufsWeb.LegacyMessage
43, // 92: WAWebProtobufsWeb.GroupHistoryBundleInfo.deprecatedMessageHistoryBundle:type_name -> WAWebProtobufsE2E.MessageHistoryBundle
44, // 92: WAWebProtobufsWeb.GroupHistoryBundleInfo.deprecatedMessageHistoryBundle:type_name -> WAWebProtobufsE2E.MessageHistoryBundle
9, // 93: WAWebProtobufsWeb.GroupHistoryBundleInfo.processState:type_name -> WAWebProtobufsWeb.GroupHistoryBundleInfo.ProcessState
39, // 94: WAWebProtobufsWeb.CommentMetadata.commentParentKey:type_name -> WACommon.MessageKey
40, // 94: WAWebProtobufsWeb.CommentMetadata.commentParentKey:type_name -> WACommon.MessageKey
10, // 95: WAWebProtobufsWeb.WebNotificationsInfo.notifyMessages:type_name -> WAWebProtobufsWeb.WebMessageInfo
39, // 96: WAWebProtobufsWeb.NotificationMessageInfo.key:type_name -> WACommon.MessageKey
40, // 97: WAWebProtobufsWeb.NotificationMessageInfo.message:type_name -> WAWebProtobufsE2E.Message
39, // 98: WAWebProtobufsWeb.Reaction.key:type_name -> WACommon.MessageKey
39, // 99: WAWebProtobufsWeb.PollUpdate.pollUpdateMessageKey:type_name -> WACommon.MessageKey
44, // 100: WAWebProtobufsWeb.PollUpdate.vote:type_name -> WAWebProtobufsE2E.PollVoteMessage
45, // 101: WAWebProtobufsWeb.KeepInChat.keepType:type_name -> WAWebProtobufsE2E.KeepType
39, // 102: WAWebProtobufsWeb.KeepInChat.key:type_name -> WACommon.MessageKey
46, // 103: WAWebProtobufsWeb.MessageAddOnContextInfo.messageAddOnExpiryType:type_name -> WAWebProtobufsE2E.MessageContextInfo.MessageAddonExpiryType
39, // 104: WAWebProtobufsWeb.EventResponse.eventResponseMessageKey:type_name -> WACommon.MessageKey
47, // 105: WAWebProtobufsWeb.EventResponse.eventResponseMessage:type_name -> WAWebProtobufsE2E.EventResponseMessage
47, // 106: WAWebProtobufsWeb.LegacyMessage.eventResponseMessage:type_name -> WAWebProtobufsE2E.EventResponseMessage
44, // 107: WAWebProtobufsWeb.LegacyMessage.pollVote:type_name -> WAWebProtobufsE2E.PollVoteMessage
40, // 108: WAWebProtobufsWeb.StatusMentionMessage.quotedStatus:type_name -> WAWebProtobufsE2E.Message
39, // 109: WAWebProtobufsWeb.GroupHistoryIndividualMessageInfo.bundleMessageKey:type_name -> WACommon.MessageKey
110, // [110:110] is the sub-list for method output_type
110, // [110:110] is the sub-list for method input_type
110, // [110:110] is the sub-list for extension type_name
110, // [110:110] is the sub-list for extension extendee
0, // [0:110] is the sub-list for field type_name
40, // 96: WAWebProtobufsWeb.NotificationMessageInfo.key:type_name -> WACommon.MessageKey
41, // 97: WAWebProtobufsWeb.NotificationMessageInfo.message:type_name -> WAWebProtobufsE2E.Message
40, // 98: WAWebProtobufsWeb.Reaction.key:type_name -> WACommon.MessageKey
40, // 99: WAWebProtobufsWeb.PollUpdate.pollUpdateMessageKey:type_name -> WACommon.MessageKey
45, // 100: WAWebProtobufsWeb.PollUpdate.vote:type_name -> WAWebProtobufsE2E.PollVoteMessage
46, // 101: WAWebProtobufsWeb.PollUpdate.metadata:type_name -> WAWebProtobufsE2E.PollUpdateMessageMetadata
39, // 102: WAWebProtobufsWeb.PollAdditionalMetadata.pollNameHashHistory:type_name -> WAWebProtobufsWeb.PollAdditionalMetadata.PollNameHashHistoryEntry
47, // 103: WAWebProtobufsWeb.KeepInChat.keepType:type_name -> WAWebProtobufsE2E.KeepType
40, // 104: WAWebProtobufsWeb.KeepInChat.key:type_name -> WACommon.MessageKey
48, // 105: WAWebProtobufsWeb.MessageAddOnContextInfo.messageAddOnExpiryType:type_name -> WAWebProtobufsE2E.MessageContextInfo.MessageAddonExpiryType
40, // 106: WAWebProtobufsWeb.EventResponse.eventResponseMessageKey:type_name -> WACommon.MessageKey
49, // 107: WAWebProtobufsWeb.EventResponse.eventResponseMessage:type_name -> WAWebProtobufsE2E.EventResponseMessage
49, // 108: WAWebProtobufsWeb.LegacyMessage.eventResponseMessage:type_name -> WAWebProtobufsE2E.EventResponseMessage
45, // 109: WAWebProtobufsWeb.LegacyMessage.pollVote:type_name -> WAWebProtobufsE2E.PollVoteMessage
41, // 110: WAWebProtobufsWeb.StatusMentionMessage.quotedStatus:type_name -> WAWebProtobufsE2E.Message
40, // 111: WAWebProtobufsWeb.GroupHistoryIndividualMessageInfo.bundleMessageKey:type_name -> WACommon.MessageKey
112, // [112:112] is the sub-list for method output_type
112, // [112:112] is the sub-list for method input_type
112, // [112:112] is the sub-list for extension type_name
112, // [112:112] is the sub-list for extension extendee
0, // [0:112] is the sub-list for field type_name
}
func init() { file_waWeb_WAWebProtobufsWeb_proto_init() }
@@ -4911,7 +5017,7 @@ func file_waWeb_WAWebProtobufsWeb_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_waWeb_WAWebProtobufsWeb_proto_rawDesc), len(file_waWeb_WAWebProtobufsWeb_proto_rawDesc)),
NumEnums: 10,
NumMessages: 29,
NumMessages: 30,
NumExtensions: 0,
NumServices: 0,
},
+13
View File
@@ -240,6 +240,10 @@ message WebMessageInfo {
GROUP_TEE_BOT_ADDED = 223;
CONTACT_INFO = 224;
SCHEDULED_MESSAGE_CREATED = 225;
IDENTITY_TRUST_MARKED = 226;
IDENTITY_TRUST_UNMARKED = 227;
IDENTITY_TRUST_REVOKED = 228;
CTWA_CONSUMER_DISCLOSURE = 230;
}
enum Status {
@@ -491,6 +495,7 @@ message GroupHistoryBundleInfo {
INJECTED_PARTIAL = 2;
INJECTION_FAILED = 3;
INJECTION_FAILED_NO_RETRY = 4;
DEDUPED = 5;
}
optional WAWebProtobufsE2E.MessageHistoryBundle deprecatedMessageHistoryBundle = 1;
@@ -518,6 +523,7 @@ message NotificationMessageInfo {
message ReportingTokenInfo {
optional bytes reportingTag = 1;
optional uint64 reportingTagTimestamp = 2;
}
message MediaData {
@@ -558,10 +564,17 @@ message PollUpdate {
optional int64 senderTimestampMS = 3;
optional int64 serverTimestampMS = 4;
optional bool unread = 5;
optional WAWebProtobufsE2E.PollUpdateMessageMetadata metadata = 6;
}
message PollAdditionalMetadata {
message PollNameHashHistoryEntry {
optional string editStanzaID = 1;
optional bytes pollNameHash = 2;
}
optional bool pollInvalidated = 1;
repeated PollNameHashHistoryEntry pollNameHashHistory = 2;
}
message InteractiveMessageAdditionalMetadata {
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,115 @@
syntax = "proto2";
package WAWebLabyrinthWaWasm;
option go_package = "go.mau.fi/whatsmeow/proto/waWebLabyrinthWaWasm";
message CreateBackupInput {
required string recoveryCode = 1;
required uint64 userID = 2;
}
message EncryptMessageInput {
required bytes epochRootKey = 1;
required bytes mailboxRootKey = 2;
required bytes orfClientState = 3;
required bytes epochAnonID = 4;
required uint64 epochID = 5;
required string threadID = 6;
required uint64 waCanonicalUserFbid = 7;
required uint64 timestampMS = 8;
required uint64 backupID = 9;
required bytes plaintextPayload = 10;
required string stanzaID = 11;
}
message DecryptMessageInput {
required bytes epochRootKey = 1;
required bytes epochAnonID = 2;
required string threadID = 3;
required int32 encryptionVersion = 4;
required bytes ciphertext = 5;
}
message OrfThreadIdInput {
required bytes orfClientState = 1;
required string threadID = 2;
}
message DeviceOutput {
required bytes publicKey = 1;
required bytes epochAuthPublicKey = 2;
required bytes epochAuthPublicKeySig = 3;
required bytes epochStoragePublicKey = 4;
required bytes epochStoragePublicKeySig = 5;
repeated int32 supportedEncryptionVersions = 6;
required bytes encryptionVersionSignature = 7;
required int32 clientVersion = 8;
required bytes ocmfClientState = 9;
}
message EncryptedSecretValuesOutput {
required bytes encryptedDevicePrivateKey = 1;
required bytes encryptedObliviousValidationTokenBlob = 2;
required bytes encryptedEpochStoragePrivateKey = 3;
required bytes encryptedOcmfClientState = 4;
optional bytes encryptedOrfClientStateV2 = 5;
required bytes encryptedMailboxRootKeyBlob = 6;
required bytes encryptedEpochAnonID = 7;
required bytes encryptedEpochRootKey = 8;
}
message VirtualDeviceOutput {
required bytes vdID = 1;
required bytes vdPublicKey = 2;
required bytes vdEpochStoragePublicKey = 3;
required bytes vdEpochStoragePublicKeySig = 4;
required bytes ocmfRotationToken = 5;
required bytes deviceEpochHmac = 6;
required EncryptedSecretValuesOutput encryptedSecretValues = 7;
}
message Epoch0Output {
required uint64 epochFbid = 1;
required bytes epochAnonID = 2;
required bytes epochData = 3;
required bytes wrappedRootKeyForSelf = 4;
required bytes epochSignature = 5;
required bytes epochRootKeyFingerprint = 6;
optional bytes epochRootKey = 7;
}
message CreateBackupOutput {
optional DeviceOutput device = 1;
optional VirtualDeviceOutput virtualDevice = 2;
optional Epoch0Output epoch0 = 3;
optional bytes mailboxRootKey = 4;
optional string error = 5;
}
message EncryptMessageOutput {
optional bytes encryptedProtobuf = 1;
optional bytes orfThreadID = 2;
optional string valueSecretRef = 3;
optional uint64 offlineThreadingID = 4;
optional uint64 timestampMS = 5;
optional bytes messageKey = 6;
optional string error = 7;
}
message DecryptMessageOutput {
optional bytes plaintextPayload = 1;
optional string error = 2;
}
message OrfThreadIdOutput {
optional bytes orfThreadID = 1;
optional string error = 2;
}
message LabyrinthWaCommand {
oneof commandInput {
CreateBackupInput createBackupInput = 1;
EncryptMessageInput encryptMessageInput = 2;
DecryptMessageInput decryptMessageInput = 3;
OrfThreadIdInput orfThreadIDInput = 4;
}
}
+50 -8
View File
@@ -8,6 +8,7 @@ package whatsmeow
import (
"context"
"fmt"
"slices"
"sync"
"sync/atomic"
@@ -27,10 +28,15 @@ type QRChannelItem struct {
Code string
// The timeout after which the next code will be sent down the channel.
Timeout time.Duration
PasskeyRequest *events.PairPasskeyRequest
PasskeyConfirmation *events.PairPasskeyConfirmation
}
const QRChannelEventCode = "code"
const QRChannelEventError = "error"
const QRChannelEventPasskeyRequest = "passkey-request"
const QRChannelEventPasskeyResponse = "passkey-confirmation"
// Possible final items in the QR channel. In addition to these, an `error` event may be emitted,
// in which case the Error field will have the error that occurred during pairing.
@@ -54,16 +60,20 @@ type qrChannel struct {
log waLog.Logger
ctx context.Context
handlerID uint32
closed uint32
closed atomic.Bool
output chan<- QRChannelItem
stopQRs chan struct{}
}
func (qrc *qrChannel) close() bool {
return qrc.closed.Swap(true) == false
}
func (qrc *qrChannel) emitQRs(codes []string) {
var nextCode string
for {
if len(codes) == 0 {
if atomic.CompareAndSwapUint32(&qrc.closed, 0, 1) {
if qrc.close() {
qrc.log.Debugf("Ran out of QR codes, closing channel with status %s and disconnecting client", QRChannelTimeout)
qrc.output <- QRChannelTimeout
close(qrc.output)
@@ -73,7 +83,7 @@ func (qrc *qrChannel) emitQRs(codes []string) {
qrc.log.Debugf("Ran out of QR codes, but channel is already closed")
}
return
} else if atomic.LoadUint32(&qrc.closed) == 1 {
} else if qrc.closed.Load() {
qrc.log.Debugf("QR code channel is closed, exiting QR emitter")
return
}
@@ -87,7 +97,7 @@ func (qrc *qrChannel) emitQRs(codes []string) {
case qrc.output <- QRChannelItem{Code: nextCode, Timeout: timeout, Event: QRChannelEventCode}:
default:
qrc.log.Debugf("Output channel didn't accept code, exiting QR emitter")
if atomic.CompareAndSwapUint32(&qrc.closed, 0, 1) {
if qrc.close() {
close(qrc.output)
go qrc.cli.RemoveEventHandler(qrc.handlerID)
qrc.cli.Disconnect()
@@ -99,9 +109,12 @@ func (qrc *qrChannel) emitQRs(codes []string) {
case <-qrc.stopQRs:
qrc.log.Debugf("Got signal to stop QR emitter")
return
case <-qrc.cli.expectedDisconnect.GetChan():
qrc.log.Debugf("Client is expected to disconnect, stopping QR emitter")
return
case <-qrc.ctx.Done():
qrc.log.Debugf("Context is done, stopping QR emitter")
if atomic.CompareAndSwapUint32(&qrc.closed, 0, 1) {
if qrc.close() {
close(qrc.output)
go qrc.cli.RemoveEventHandler(qrc.handlerID)
qrc.cli.Disconnect()
@@ -110,8 +123,8 @@ func (qrc *qrChannel) emitQRs(codes []string) {
}
}
func (qrc *qrChannel) handleEvent(rawEvt interface{}) {
if atomic.LoadUint32(&qrc.closed) == 1 {
func (qrc *qrChannel) handleEvent(rawEvt any) {
if qrc.closed.Load() {
qrc.log.Debugf("Dropping event of type %T, channel is closed", rawEvt)
return
}
@@ -125,6 +138,35 @@ func (qrc *qrChannel) handleEvent(rawEvt interface{}) {
qrc.log.Debugf("QR code scanned without multidevice enabled")
qrc.output <- QRChannelScannedWithoutMultidevice
return
case *events.PairPasskeyRequest:
qrc.output <- QRChannelItem{
Event: QRChannelEventPasskeyRequest,
PasskeyRequest: evt,
}
return
case *events.PairPasskeyConfirmation:
if evt.SkipHandoffUX {
qrc.log.Debugf("Sending automatic passkey confirmation")
err := qrc.cli.SendPasskeyConfirmation(qrc.ctx)
if err != nil {
qrc.output <- QRChannelItem{
Event: QRChannelEventError,
Error: fmt.Errorf("failed to send passkey confirmation automatically: %w", err),
}
}
} else {
qrc.output <- QRChannelItem{
Event: QRChannelEventPasskeyResponse,
PasskeyConfirmation: evt,
}
}
return
case *events.PairPasskeyError:
qrc.output <- QRChannelItem{
Event: QRChannelEventError,
Error: evt.Error,
}
return
case *events.ClientOutdated:
outputType = QRChannelClientOutdated
case *events.PairSuccess:
@@ -142,7 +184,7 @@ func (qrc *qrChannel) handleEvent(rawEvt interface{}) {
return
}
close(qrc.stopQRs)
if atomic.CompareAndSwapUint32(&qrc.closed, 0, 1) {
if qrc.close() {
qrc.log.Debugf("Closing channel with status %+v", outputType)
qrc.output <- outputType
close(qrc.output)
+2 -2
View File
@@ -38,7 +38,7 @@ func (cli *Client) handleGroupedReceipt(partialReceipt events.Receipt, participa
partialReceipt.MessageIDs = []types.MessageID{pag.String("key")}
for _, child := range participants.GetChildren() {
if child.Tag != "user" {
cli.Log.Warnf("Unexpected node in grouped receipt participants: %s", child.XMLString())
cli.Log.Warnf("Unexpected node in grouped receipt participants: %s", &child)
continue
}
ag := child.AttrGetter()
@@ -46,7 +46,7 @@ func (cli *Client) handleGroupedReceipt(partialReceipt events.Receipt, participa
receipt.Timestamp = ag.UnixTime("t")
receipt.MessageSource.Sender = ag.JID("jid")
if !ag.OK() {
cli.Log.Warnf("Failed to parse user node %s in grouped receipt: %v", child.XMLString(), ag.Error())
cli.Log.Warnf("Failed to parse user node %s in grouped receipt: %v", &child, ag.Error())
continue
}
cli.dispatchEvent(&receipt)
+4 -4
View File
@@ -102,7 +102,7 @@ type infoQuery struct {
Target types.JID
ID string
SMaxID string
Content interface{}
Content any
Timeout time.Duration
NoRetry bool
@@ -191,11 +191,11 @@ func (cli *Client) retryFrame(
timeout time.Duration,
) (*waBinary.Node, error) {
if isAuthErrorDisconnect(origResp) {
cli.Log.Debugf("%s (%s) was interrupted by websocket disconnection (%s), not retrying as it looks like an auth error", id, reqType, origResp.XMLString())
cli.Log.Debugf("%s (%s) was interrupted by websocket disconnection (%s), not retrying as it looks like an auth error", id, reqType, origResp)
return nil, &DisconnectedError{Action: reqType, Node: origResp}
}
cli.Log.Debugf("%s (%s) was interrupted by websocket disconnection (%s), waiting for reconnect to retry...", id, reqType, origResp.XMLString())
cli.Log.Debugf("%s (%s) was interrupted by websocket disconnection (%s), waiting for reconnect to retry...", id, reqType, origResp)
if !cli.WaitForConnection(5 * time.Second) {
cli.Log.Debugf("Websocket didn't reconnect within 5 seconds of failed %s (%s)", reqType, id)
return nil, &DisconnectedError{Action: reqType, Node: origResp}
@@ -228,7 +228,7 @@ func (cli *Client) retryFrame(
return nil, ErrIQTimedOut
}
if isDisconnectNode(resp) {
cli.Log.Debugf("Retrying %s %s was interrupted by websocket disconnection (%v), not retrying anymore", reqType, id, resp.XMLString())
cli.Log.Debugf("Retrying %s %s was interrupted by websocket disconnection (%s), not retrying anymore", reqType, id, resp)
return nil, &DisconnectedError{Action: fmt.Sprintf("%s (retry)", reqType), Node: resp}
}
return resp, nil
+18 -5
View File
@@ -322,7 +322,11 @@ func (cli *Client) SendMessage(ctx context.Context, to types.JID, message *waE2E
resp.DebugTimings.GetParticipants = time.Since(start)
} else if to.Server == types.HiddenUserServer {
ownID = cli.getOwnLID()
} else if to.Server == types.DefaultUserServer && cli.Store.LIDMigrationTimestamp > 0 && !req.Peer {
extraParams.peerRecipientPN, err = cli.Store.LIDs.GetPNForLID(ctx, to)
if err != nil {
cli.Log.Warnf("Failed to get peer recipient PN for %s: %v", to, err)
}
} else if to.Server == types.DefaultUserServer && !req.Peer {
start := time.Now()
var toLID types.JID
toLID, err = cli.Store.LIDs.GetLIDForPN(ctx, to)
@@ -331,6 +335,7 @@ func (cli *Client) SendMessage(ctx context.Context, to types.JID, message *waE2E
return
} else if toLID.IsEmpty() {
var info map[types.JID]types.UserInfo
cli.Log.Debugf("LID for %s not found, fetching user info", to)
info, err = cli.GetUserInfo(ctx, []types.JID{to})
if err != nil {
err = fmt.Errorf("failed to get user info for %s to fill LID cache: %w", to, err)
@@ -341,7 +346,8 @@ func (cli *Client) SendMessage(ctx context.Context, to types.JID, message *waE2E
}
}
resp.DebugTimings.LIDFetch = time.Since(start)
cli.Log.Debugf("Replacing SendMessage destination with LID as migration timestamp is set %s -> %s", to, toLID)
cli.Log.Debugf("Replacing SendMessage destination with LID %s -> %s", to, toLID)
extraParams.peerRecipientPN = to
to = toLID
ownID = cli.getOwnLID()
}
@@ -742,6 +748,7 @@ type nodeExtraParams struct {
metaNode *waBinary.Node
additionalNodes *[]waBinary.Node
addressingMode types.AddressingMode
peerRecipientPN types.JID
}
func (cli *Client) sendGroup(
@@ -1187,6 +1194,9 @@ func (cli *Client) prepareMessageNode(
"type": msgType,
"to": to,
}
if !extraParams.peerRecipientPN.IsEmpty() {
attrs["peer_recipient_pn"] = extraParams.peerRecipientPN
}
// TODO this is a very hacky hack for announcement group messages, why is it pn anyway?
if extraParams.addressingMode != "" {
attrs["addressing_mode"] = string(extraParams.addressingMode)
@@ -1285,6 +1295,9 @@ func (cli *Client) encryptMessageForDevices(
sessionAddressToJID := make(map[string]types.JID, len(allDevices))
sessionAddresses := make([]string, 0, len(allDevices))
for _, jid := range allDevices {
if jid == ownJID || jid == ownLID {
continue
}
encryptionIdentity := jid
if jid.Server == types.DefaultUserServer {
// TODO query LID from server for missing entries
@@ -1313,10 +1326,10 @@ func (cli *Client) encryptMessageForDevices(
for _, jid := range allDevices {
plaintext := msgPlaintext
if jid == ownJID || jid == ownLID {
continue
}
if (jid.User == ownJID.User || jid.User == ownLID.User) && dsmPlaintext != nil {
if jid == ownJID || jid == ownLID {
continue
}
plaintext = dsmPlaintext
}
encrypted, isPreKey, err := cli.encryptMessageForDeviceAndWrap(
+6 -3
View File
@@ -530,6 +530,9 @@ func (cli *Client) encryptMessageForDevicesV3(
sessionAddressToJID := make(map[string]types.JID, len(allDevices))
sessionAddresses := make([]string, 0, len(allDevices))
for _, jid := range allDevices {
if jid == ownID {
continue
}
addr := jid.SignalAddress().String()
sessionAddresses = append(sessionAddresses, addr)
sessionAddressToJID[addr] = jid
@@ -547,11 +550,11 @@ func (cli *Client) encryptMessageForDevicesV3(
bundles := cli.fetchPreKeysNoError(ctx, retryDevices)
for _, jid := range allDevices {
if jid == ownID {
continue
}
var dsmForDevice *waMsgTransport.MessageTransport_Protocol_Integral_DeviceSentMessage
if jid.User == ownID.User {
if jid == ownID {
continue
}
dsmForDevice = dsm
}
encrypted, err := cli.encryptMessageForDeviceAndWrapV3(ctx, payload, skdm, dsmForDevice, jid, bundles[jid], encAttrs)
+13 -12
View File
@@ -12,6 +12,7 @@ import (
"fmt"
"net/http"
"sync"
"sync/atomic"
"github.com/coder/websocket"
@@ -22,7 +23,7 @@ type FrameSocket struct {
parentCtx context.Context
cancelCtx context.Context
cancel context.CancelFunc
conn *websocket.Conn
conn atomic.Pointer[websocket.Conn]
log waLog.Logger
lock sync.Mutex
@@ -35,7 +36,7 @@ type FrameSocket struct {
Header []byte
closed bool
closed atomic.Bool
incomingLength int
receivedLength int
@@ -56,30 +57,30 @@ func NewFrameSocket(log waLog.Logger, client *http.Client) *FrameSocket {
}
func (fs *FrameSocket) IsConnected() bool {
return fs.conn != nil
return fs.conn.Load() != nil
}
func (fs *FrameSocket) Close(code websocket.StatusCode) {
fs.lock.Lock()
defer fs.lock.Unlock()
if fs.conn == nil {
conn := fs.conn.Swap(nil)
if conn == nil {
return
}
fs.closed = true
fs.closed.Store(true)
if code > 0 {
err := fs.conn.Close(code, "")
err := conn.Close(code, "")
if err != nil {
fs.log.Warnf("Error sending close to websocket: %v", err)
}
} else {
err := fs.conn.CloseNow()
err := conn.CloseNow()
if err != nil {
fs.log.Debugf("Error force closing websocket: %v", err)
}
}
fs.conn = nil
fs.cancel()
fs.cancel = nil
if fs.OnDisconnect != nil {
@@ -90,7 +91,7 @@ func (fs *FrameSocket) Close(code websocket.StatusCode) {
func (fs *FrameSocket) Connect(ctx context.Context) error {
fs.lock.Lock()
defer fs.lock.Unlock()
if fs.conn != nil {
if fs.conn.Load() != nil {
return ErrSocketAlreadyOpen
}
fs.parentCtx = ctx
@@ -107,7 +108,7 @@ func (fs *FrameSocket) Connect(ctx context.Context) error {
}
conn.SetReadLimit(FrameMaxSize)
fs.conn = conn
fs.conn.Store(conn)
go fs.readPump(conn, ctx)
return nil
@@ -118,7 +119,7 @@ func (fs *FrameSocket) Context() context.Context {
}
func (fs *FrameSocket) SendFrame(data []byte) error {
conn := fs.conn
conn := fs.conn.Load()
if conn == nil {
return ErrSocketClosed
}
@@ -209,7 +210,7 @@ func (fs *FrameSocket) readPump(conn *websocket.Conn, ctx context.Context) {
msgType, data, err := conn.Read(ctx)
if err != nil {
// Ignore the error if the context has been closed
if !fs.closed && !errors.Is(ctx.Err(), context.Canceled) {
if !fs.closed.Load() && !errors.Is(ctx.Err(), context.Canceled) {
fs.log.Errorf("Error reading from websocket: %v", err)
}
return
+22
View File
@@ -0,0 +1,22 @@
// Copyright (c) 2026 Tulir Asokan
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package whatsmeow
import (
"context"
waBinary "go.mau.fi/whatsmeow/binary"
)
// handleStatusUpdate acknowledges <status> stanzas (channel status updates).
// The content isn't parsed into events yet, but the stanza must be acked:
// otherwise the server redelivers it on every connect and recycles the
// connection every 50 minutes with
// <stream:error><ack class="status" id="..." type="..."/></stream:error>.
func (cli *Client) handleStatusUpdate(ctx context.Context, node *waBinary.Node) {
defer cli.maybeDeferredAck(ctx, node)()
}
+2 -2
View File
@@ -76,7 +76,7 @@ func (vc WAVersionContainer) ProtoAppVersion() *waWa6.ClientPayload_UserAgent_Ap
}
// waVersion is the WhatsApp web client version
var waVersion = WAVersionContainer{2, 3000, 1039406452}
var waVersion = WAVersionContainer{2, 3000, 1043045417}
// waVersionHash is the md5 hash of a dot-separated waVersion
var waVersionHash = waVersion.Hash()
@@ -134,7 +134,7 @@ var DeviceProps = &waCompanionReg.DeviceProps{
StorageQuotaMb: proto.Uint32(10240),
InlineInitialPayloadInE2EeMsg: proto.Bool(true),
RecentSyncDaysLimit: nil,
SupportCallLogHistory: proto.Bool(false),
SupportCallLogHistory: proto.Bool(true),
SupportBotUserAgentChatHistory: proto.Bool(true),
SupportCagReactionsAndPolls: proto.Bool(true),
SupportBizHostedMsg: proto.Bool(true),
+2 -12
View File
@@ -51,6 +51,7 @@ func New(ctx context.Context, dialect, address string, log waLog.Logger) (*Conta
container := NewWithDB(db, dialect, log)
err = container.Upgrade(ctx)
if err != nil {
_ = container.Close()
return nil, fmt.Errorf("failed to upgrade database: %w", err)
}
return container, nil
@@ -155,18 +156,7 @@ func (c *Container) scanDevice(row dbutil.Scannable) (*store.Device, error) {
// GetAllDevices finds all the devices in the database.
func (c *Container) GetAllDevices(ctx context.Context) ([]*store.Device, error) {
res, err := c.db.Query(ctx, getAllDevicesQuery)
if err != nil {
return nil, fmt.Errorf("failed to query sessions: %w", err)
}
sessions := make([]*store.Device, 0)
for res.Next() {
sess, scanErr := c.scanDevice(res)
if scanErr != nil {
return sessions, scanErr
}
sessions = append(sessions, sess)
}
return sessions, nil
return dbutil.NewRowIterWithError(res, c.scanDevice, err).AsList()
}
// GetFirstDevice is a convenience method for getting the first device in the store. If there are
+36 -33
View File
@@ -56,37 +56,36 @@ const (
getAllLIDMappingsQuery = `SELECT lid, pn FROM whatsmeow_lid_map`
)
var convertLIDRow = dbutil.ConvertRowFn[store.LIDMapping](func(rows dbutil.Scannable) (store.LIDMapping, error) {
var lidUser, pnUser string
err := rows.Scan(&lidUser, &pnUser)
if err != nil {
return store.LIDMapping{}, err
}
return store.LIDMapping{
LID: types.JID{User: lidUser, Server: types.DefaultUserServer},
PN: types.JID{User: pnUser, Server: types.DefaultUserServer},
}, nil
})
func (s *CachedLIDMap) FillCache(ctx context.Context) error {
s.lidCacheLock.Lock()
defer s.lidCacheLock.Unlock()
rows, err := s.db.Query(ctx, getAllLIDMappingsQuery)
if err != nil {
return err
}
err = s.scanManyLids(rows, nil)
res := convertLIDRow.NewRowIter(s.db.Query(ctx, getAllLIDMappingsQuery))
err := s.scanManyLids(res, nil)
s.cacheFilled = err == nil
return err
}
func (s *CachedLIDMap) scanManyLids(rows dbutil.Rows, fn func(lid, pn string)) error {
if fn == nil {
fn = func(lid, pn string) {}
}
for rows.Next() {
var lid, pn string
err := rows.Scan(&lid, &pn)
if err != nil {
return err
func (s *CachedLIDMap) scanManyLids(res dbutil.RowIter[store.LIDMapping], fn func(lid, pn string)) error {
return res.Iter(func(mapping store.LIDMapping) (bool, error) {
s.pnToLIDCache[mapping.PN.User] = mapping.LID.User
s.lidToPNCache[mapping.LID.User] = mapping.PN.User
if fn != nil {
fn(mapping.LID.User, mapping.PN.User)
}
s.pnToLIDCache[pn] = lid
s.lidToPNCache[lid] = pn
fn(lid, pn)
}
err := rows.Close()
if err != nil {
return err
}
return rows.Err()
return true, nil
})
}
func (s *CachedLIDMap) getLIDMapping(ctx context.Context, source types.JID, targetServer, query string, sourceToTarget, targetToSource map[string]string) (types.JID, error) {
@@ -166,29 +165,25 @@ func (s *CachedLIDMap) GetManyLIDsForPNs(ctx context.Context, pns []types.JID) (
s.lidCacheLock.Lock()
defer s.lidCacheLock.Unlock()
var rows dbutil.Rows
var err error
var res dbutil.RowIter[store.LIDMapping]
if s.db.Dialect == dbutil.Postgres && PostgresArrayWrapper != nil {
rows, err = s.db.Query(
res = convertLIDRow.NewRowIter(s.db.Query(
ctx,
`SELECT lid, pn FROM whatsmeow_lid_map WHERE pn = ANY($1)`,
PostgresArrayWrapper(missingPNs),
)
))
} else {
placeholders := make([]string, len(missingPNs))
for i := range missingPNs {
placeholders[i] = fmt.Sprintf("$%d", i+1)
}
rows, err = s.db.Query(
res = convertLIDRow.NewRowIter(s.db.Query(
ctx,
fmt.Sprintf(`SELECT lid, pn FROM whatsmeow_lid_map WHERE pn IN (%s)`, strings.Join(placeholders, ",")),
exslices.CastToAny(missingPNs)...,
)
))
}
if err != nil {
return nil, err
}
err = s.scanManyLids(rows, func(lid, pn string) {
err := s.scanManyLids(res, func(lid, pn string) {
for _, dev := range missingPNDevices[pn] {
lidDev := dev
lidDev.Server = types.HiddenUserServer
@@ -258,7 +253,15 @@ func (s *CachedLIDMap) unlockedPutLIDMapping(ctx context.Context, lid, pn types.
if err != nil {
return err
}
oldLID := s.pnToLIDCache[pn.User]
oldPN := s.lidToPNCache[lid.User]
s.pnToLIDCache[pn.User] = lid.User
s.lidToPNCache[lid.User] = pn.User
if oldPN != "" && oldPN != pn.User && s.pnToLIDCache[oldPN] == lid.User {
delete(s.pnToLIDCache, oldPN)
}
if oldLID != "" && oldLID != lid.User && s.lidToPNCache[oldLID] == pn.User {
delete(s.lidToPNCache, oldLID)
}
return nil
}
+44 -53
View File
@@ -343,30 +343,20 @@ func (s *SQLStore) GetOrGenPreKeys(ctx context.Context, count uint32) ([]*keys.P
s.preKeyLock.Lock()
defer s.preKeyLock.Unlock()
res, err := s.db.Query(ctx, getUnuploadedPreKeysQuery, s.JID, count)
newKeys, err := scanPreKey.NewRowIter(s.db.Query(ctx, getUnuploadedPreKeysQuery, s.JID, count)).AsList()
if err != nil {
return nil, fmt.Errorf("failed to query existing prekeys: %w", err)
}
newKeys := make([]*keys.PreKey, count)
var existingCount uint32
for res.Next() {
var key *keys.PreKey
key, err = scanPreKey(res)
if err != nil {
return nil, err
} else if key != nil {
newKeys[existingCount] = key
existingCount++
}
}
if existingCount < uint32(len(newKeys)) {
alreadyGeneratedCount := uint32(len(newKeys))
if count > alreadyGeneratedCount {
var nextKeyID uint32
nextKeyID, err = s.getNextPreKeyID(ctx)
if err != nil {
return nil, err
}
for i := existingCount; i < count; i++ {
newKeys = slices.Grow(newKeys, int(count)-len(newKeys))[:count]
for i := alreadyGeneratedCount; i < count; i++ {
newKeys[i], err = s.genOnePreKey(ctx, nextKeyID, false)
if err != nil {
return nil, fmt.Errorf("failed to generate prekey: %w", err)
@@ -378,7 +368,7 @@ func (s *SQLStore) GetOrGenPreKeys(ctx context.Context, count uint32) ([]*keys.P
return newKeys, nil
}
func scanPreKey(row dbutil.Scannable) (*keys.PreKey, error) {
var scanPreKey = dbutil.ConvertRowFn[*keys.PreKey](func(row dbutil.Scannable) (*keys.PreKey, error) {
var priv []byte
var id uint32
err := row.Scan(&id, &priv)
@@ -393,7 +383,7 @@ func scanPreKey(row dbutil.Scannable) (*keys.PreKey, error) {
KeyPair: *keys.NewKeyPairFromPrivateKey(*(*[32]byte)(priv)),
KeyID: id,
}, nil
}
})
func (s *SQLStore) GetPreKey(ctx context.Context, id uint32) (*keys.PreKey, error) {
return scanPreKey(s.db.QueryRow(ctx, getPreKeyQuery, s.JID, id))
@@ -452,32 +442,25 @@ func (s *SQLStore) PutAppStateSyncKey(ctx context.Context, id []byte, key store.
return err
}
func (s *SQLStore) GetAllAppStateSyncKeys(ctx context.Context) ([]*store.AppStateSyncKey, error) {
rows, err := s.db.Query(ctx, getAllAppStateSyncKeysQuery, s.JID)
var convertAppStateSyncKeyRow = dbutil.ConvertRowFn[*store.AppStateSyncKey](func(rows dbutil.Scannable) (*store.AppStateSyncKey, error) {
var item store.AppStateSyncKey
err := rows.Scan(&item.Data, &item.Timestamp, &item.Fingerprint)
if err != nil {
return nil, err
}
var out []*store.AppStateSyncKey
for rows.Next() {
var item store.AppStateSyncKey
err = rows.Scan(&item.Data, &item.Timestamp, &item.Fingerprint)
if err != nil {
return nil, err
}
if len(item.Data) > 0 {
out = append(out, &item)
}
}
return out, rows.Close()
return &item, nil
})
func (s *SQLStore) GetAllAppStateSyncKeys(ctx context.Context) ([]*store.AppStateSyncKey, error) {
return convertAppStateSyncKeyRow.NewRowIter(s.db.Query(ctx, getAllAppStateSyncKeysQuery, s.JID)).AsList()
}
func (s *SQLStore) GetAppStateSyncKey(ctx context.Context, id []byte) (*store.AppStateSyncKey, error) {
var key store.AppStateSyncKey
err := s.db.QueryRow(ctx, getAppStateSyncKeyQuery, s.JID, id).Scan(&key.Data, &key.Timestamp, &key.Fingerprint)
key, err := convertAppStateSyncKeyRow(s.db.QueryRow(ctx, getAppStateSyncKeyQuery, s.JID, id))
if errors.Is(err, sql.ErrNoRows) {
return nil, nil
}
return &key, err
return key, err
}
func (s *SQLStore) GetLatestAppStateSyncKeyID(ctx context.Context) ([]byte, error) {
@@ -794,33 +777,41 @@ func (s *SQLStore) GetContact(ctx context.Context, user types.JID) (types.Contac
return *info, nil
}
func (s *SQLStore) GetAllContacts(ctx context.Context) (map[types.JID]types.ContactInfo, error) {
s.contactCacheLock.Lock()
defer s.contactCacheLock.Unlock()
rows, err := s.db.Query(ctx, getAllContactsQuery, s.JID)
type contactTuple struct {
JID types.JID
Info *types.ContactInfo
}
var convertContactRow = dbutil.ConvertRowFn[*contactTuple](func(rows dbutil.Scannable) (*contactTuple, error) {
var jid types.JID
var first, full, push, business, redactedPhone sql.NullString
err := rows.Scan(&jid, &first, &full, &push, &business, &redactedPhone)
if err != nil {
return nil, err
return nil, fmt.Errorf("error scanning row: %w", err)
}
output := make(map[types.JID]types.ContactInfo, len(s.contactCache))
for rows.Next() {
var jid types.JID
var first, full, push, business, redactedPhone sql.NullString
err = rows.Scan(&jid, &first, &full, &push, &business, &redactedPhone)
if err != nil {
return nil, fmt.Errorf("error scanning row: %w", err)
}
info := types.ContactInfo{
return &contactTuple{
JID: jid,
Info: &types.ContactInfo{
Found: true,
FirstName: first.String,
FullName: full.String,
PushName: push.String,
BusinessName: business.String,
RedactedPhone: redactedPhone.String,
}
output[jid] = info
s.contactCache[jid] = &info
}
return output, nil
},
}, nil
})
func (s *SQLStore) GetAllContacts(ctx context.Context) (map[types.JID]types.ContactInfo, error) {
s.contactCacheLock.Lock()
defer s.contactCacheLock.Unlock()
output := make(map[types.JID]types.ContactInfo, len(s.contactCache))
err := convertContactRow.NewRowIter(s.db.Query(ctx, getAllContactsQuery, s.JID)).Iter(func(tuple *contactTuple) (bool, error) {
output[tuple.JID] = *tuple.Info
s.contactCache[tuple.JID] = tuple.Info
return true, nil
})
return output, err
}
const (
+4 -1
View File
@@ -56,7 +56,7 @@ func shouldSendTCTokenInChatAction(jid types.JID) bool {
func (cli *Client) resolveTCTokenStorageLID(ctx context.Context, jid types.JID) types.JID {
storageJID := jid.ToNonAD()
if storageJID.Server != types.DefaultUserServer || cli.Store == nil || cli.Store.LIDs == nil {
if storageJID.Server != types.DefaultUserServer {
return storageJID
}
lid, err := cli.Store.LIDs.GetLIDForPN(ctx, storageJID)
@@ -118,6 +118,9 @@ func (cli *Client) unlockedCleanupTCTokenSenderTSMap() {
// ensureTCToken returns a stored non-expired tctoken for the given JID, if available.
func (cli *Client) ensureTCToken(ctx context.Context, jid types.JID) (token []byte, err error) {
if cli.getOwnID().IsEmpty() {
return nil, ErrNotLoggedIn
}
cli.deleteExpiredPrivacyTokens()
storageJID := cli.resolveTCTokenStorageLID(ctx, jid)
existing, err := cli.Store.PrivacyTokens.GetPrivacyToken(ctx, storageJID)
+40
View File
@@ -12,10 +12,13 @@ import (
"strconv"
"time"
"go.mau.fi/util/jsontime"
waBinary "go.mau.fi/whatsmeow/binary"
armadillo "go.mau.fi/whatsmeow/proto"
"go.mau.fi/whatsmeow/proto/instamadilloTransportPayload"
"go.mau.fi/whatsmeow/proto/waArmadilloApplication"
"go.mau.fi/whatsmeow/proto/waCompanionReg"
"go.mau.fi/whatsmeow/proto/waConsumerApplication"
"go.mau.fi/whatsmeow/proto/waE2E"
"go.mau.fi/whatsmeow/proto/waHistorySync"
@@ -46,6 +49,7 @@ type PairSuccess struct {
LID types.JID
BusinessName string
Platform string
Props *waCompanionReg.ClientPairingProps
}
// PairError is emitted when a pair-success event is received from the server, but finishing the pairing locally fails.
@@ -54,9 +58,30 @@ type PairError struct {
LID types.JID
BusinessName string
Platform string
Props *waCompanionReg.ClientPairingProps
Error error
}
// PairPasskeyRequest is emitted when the pairing requires a passkey.
// The client should generate a response and send it using Client.SendPasskeyResponse.
type PairPasskeyRequest struct {
PublicKey *types.WebAuthnPublicKey
}
// PairPasskeyError is emitted if handling a passkey notification fails.
type PairPasskeyError struct {
Error error
Continuation bool // Whether this was from a continuation notification rather than the initial one
}
// PairPasskeyConfirmation is emitted after a successful SendPasskeyResponse call.
// If SkipHandoffUX is false, the user should be shown the code and asked to verify that it matches the one on their phone.
// After verification if needed, the client should call Client.SendPasskeyConfirmation to finish the pairing process.
type PairPasskeyConfirmation struct {
Code string
SkipHandoffUX bool
}
// QRScannedWithoutMultidevice is emitted when the pairing QR code is scanned, but the phone didn't have multidevice enabled.
// The same QR code can still be scanned after this event, which means the user can just be told to enable multidevice and re-scan the code.
type QRScannedWithoutMultidevice struct{}
@@ -602,16 +627,24 @@ type BlocklistChange struct {
Action BlocklistChangeAction
}
type MexNotificationData struct {
Timestamp time.Time
OpName string
}
type NewsletterJoin struct {
Mex MexNotificationData `json:"-"`
types.NewsletterMetadata
}
type NewsletterLeave struct {
Mex MexNotificationData `json:"-"`
ID types.JID `json:"id"`
Role types.NewsletterRole `json:"role"`
}
type NewsletterMuteChange struct {
Mex MexNotificationData `json:"-"`
ID types.JID `json:"id"`
Mute types.NewsletterMuteState `json:"mute"`
}
@@ -621,3 +654,10 @@ type NewsletterLiveUpdate struct {
Time time.Time
Messages []*types.NewsletterMessage
}
type NotifyAccountReachoutTimelock struct {
Mex MexNotificationData `json:"-"`
EnforcementType string `json:"enforcement_type,omitempty"`
IsActive bool `json:"is_active,omitempty"`
TimeEnforcementEnds jsontime.UnixString `json:"time_enforcement_ends,omitzero"`
}
+1 -1
View File
@@ -248,7 +248,7 @@ func (jid JID) IsEmpty() bool {
var _ sql.Scanner = (*JID)(nil)
// Scan scans the given SQL value into this JID.
func (jid *JID) Scan(src interface{}) error {
func (jid *JID) Scan(src any) error {
if src == nil {
return nil
}
+40
View File
@@ -0,0 +1,40 @@
// Copyright (c) 2026 Tulir Asokan
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package types
import (
"go.mau.fi/util/jsonbytes"
)
type WebAuthnPublicKey struct {
Challenge jsonbytes.UnpaddedURLBytes `json:"challenge"`
Timeout int `json:"timeout"`
RelyingPartID string `json:"rpId"`
AllowCredentials []AllowedCredential `json:"allowCredentials"`
UserVerification string `json:"userVerification"`
Extensions map[string]any `json:"extensions"`
}
type AllowedCredential struct {
ID jsonbytes.UnpaddedURLBytes `json:"id"`
Type string `json:"type"`
Transports []string `json:"transports"`
}
type WebAuthnResponse struct {
ID string `json:"id"`
RawID jsonbytes.UnpaddedURLBytes `json:"rawId"`
Type string `json:"type"`
Response WebAuthnResponseData `json:"response"`
}
type WebAuthnResponseData struct {
ClientDataJSON jsonbytes.UnpaddedURLBytes `json:"clientDataJSON"`
AuthenticatorData jsonbytes.UnpaddedURLBytes `json:"authenticatorData"`
Signature jsonbytes.UnpaddedURLBytes `json:"signature"`
UserHandle *jsonbytes.UnpaddedURLBytes `json:"userHandle"`
}
+8
View File
@@ -16,6 +16,12 @@ import (
type VerifiedName struct {
Certificate *waVnameCert.VerifiedNameCertificate
Details *waVnameCert.VerifiedNameCertificate_Details
VerifiedLevel string
Version int
HostStorage int
ActualActors int
PrivacyModeTS time.Time
}
// UserInfo contains info about a WhatsApp user.
@@ -88,6 +94,8 @@ type IsOnWhatsAppResponse struct {
JID JID // The canonical user ID
IsIn bool // Whether the phone is registered or not.
PhoneNumber JID
VerifiedName *VerifiedName // If the phone is a business, the verified business details.
}
+1 -1
View File
@@ -34,7 +34,7 @@ func GetLatestVersion(ctx context.Context, httpClient *http.Client) (*store.WAVe
if err != nil {
return nil, fmt.Errorf("failed to prepare request: %w", err)
}
req.Header.Set("User-Agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36")
req.Header.Set("User-Agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36")
req.Header.Set("Sec-Fetch-Dest", "document")
req.Header.Set("Sec-Fetch-Mode", "navigate")
req.Header.Set("Sec-Fetch-Site", "none")
+66 -14
View File
@@ -32,15 +32,29 @@ const (
NewsletterLinkPrefix = "https://whatsapp.com/channel/"
)
func stripQuery(link string) string {
if idx := strings.Index(link, "?"); idx > 0 {
return link[:idx]
}
return link
}
func stripURLPrefix(link string, prefixes ...string) string {
for _, prefix := range prefixes {
unprefixed, ok := strings.CutPrefix(link, prefix)
if ok {
return stripQuery(unprefixed)
}
}
return link
}
// ResolveBusinessMessageLink resolves a business message short link and returns the target JID, business name and
// text to prefill in the input field (if any).
//
// The links look like https://wa.me/message/<code> or https://api.whatsapp.com/message/<code>. You can either provide
// the full link, or just the <code> part.
func (cli *Client) ResolveBusinessMessageLink(ctx context.Context, code string) (*types.BusinessMessageLinkTarget, error) {
code = strings.TrimPrefix(code, BusinessMessageLinkPrefix)
code = strings.TrimPrefix(code, BusinessMessageLinkDirectPrefix)
resp, err := cli.sendIQ(ctx, infoQuery{
Namespace: "w:qr",
Type: iqGet,
@@ -48,7 +62,7 @@ func (cli *Client) ResolveBusinessMessageLink(ctx context.Context, code string)
Content: []waBinary.Node{{
Tag: "qr",
Attrs: waBinary.Attrs{
"code": code,
"code": stripURLPrefix(code, BusinessMessageLinkPrefix, BusinessMessageLinkDirectPrefix),
},
}},
})
@@ -85,16 +99,13 @@ func (cli *Client) ResolveBusinessMessageLink(ctx context.Context, code string)
// The links look like https://wa.me/qr/<code> or https://api.whatsapp.com/qr/<code>. You can either provide
// the full link, or just the <code> part.
func (cli *Client) ResolveContactQRLink(ctx context.Context, code string) (*types.ContactQRLinkTarget, error) {
code = strings.TrimPrefix(code, ContactQRLinkPrefix)
code = strings.TrimPrefix(code, ContactQRLinkDirectPrefix)
resp, err := cli.sendIQ(ctx, infoQuery{
Namespace: "w:qr",
Type: iqGet,
Content: []waBinary.Node{{
Tag: "qr",
Attrs: waBinary.Attrs{
"code": code,
"code": stripURLPrefix(code, ContactQRLinkPrefix, ContactQRLinkDirectPrefix),
},
}},
})
@@ -171,21 +182,36 @@ func (cli *Client) IsOnWhatsApp(ctx context.Context, phones []string) ([]types.I
jids[i] = types.NewJID(phones[i], types.LegacyUserServer)
}
list, err := cli.usync(ctx, jids, "query", "interactive", []waBinary.Node{
{Tag: "contact", Attrs: waBinary.Attrs{"addressing_mode": "lid"}},
{Tag: "business", Content: []waBinary.Node{{Tag: "verified_name"}}},
{Tag: "contact"},
{Tag: "disappearing_mode"},
{Tag: "username"},
})
if err != nil {
return nil, err
}
output := make([]types.IsOnWhatsAppResponse, 0, len(jids))
lidEntries := make([]store.LIDMapping, 0, len(jids))
querySuffix := "@" + types.LegacyUserServer
for _, child := range list.GetChildren() {
jid, jidOK := child.Attrs["jid"].(types.JID)
if child.Tag != "user" || !jidOK {
ag := child.AttrGetter()
jid := ag.OptionalJIDOrEmpty("jid")
pnJID := ag.OptionalJIDOrEmpty("pn_jid")
if child.Tag != "user" || (jid.IsEmpty() && pnJID.IsEmpty()) {
continue
}
var info types.IsOnWhatsAppResponse
info.JID = jid
if jid.IsEmpty() {
info.JID = pnJID
}
info.PhoneNumber = pnJID
if info.JID.Server == types.HiddenUserServer && info.PhoneNumber.Server == types.DefaultUserServer {
lidEntries = append(lidEntries, store.LIDMapping{
LID: info.JID,
PN: info.PhoneNumber,
})
}
info.VerifiedName, err = parseVerifiedName(child.GetChildByTag("business"))
if err != nil {
cli.Log.Warnf("Failed to parse %s's verified name details: %v", jid, err)
@@ -196,6 +222,12 @@ func (cli *Client) IsOnWhatsApp(ctx context.Context, phones []string) ([]types.I
info.Query = strings.TrimSuffix(string(contactQuery), querySuffix)
output = append(output, info)
}
if len(lidEntries) > 0 {
err = cli.Store.LIDs.PutManyLIDMappings(ctx, lidEntries)
if err != nil {
return output, fmt.Errorf("failed to store LID mappings: %w", err)
}
}
return output, nil
}
@@ -207,6 +239,8 @@ func (cli *Client) GetUserInfo(ctx context.Context, jids []types.JID) (map[types
{Tag: "picture"},
{Tag: "devices", Attrs: waBinary.Attrs{"version": "2"}},
{Tag: "lid"},
}, UsyncQueryExtras{
IncludePrivacyToken: true,
})
if err != nil {
return nil, err
@@ -566,10 +600,10 @@ func (cli *Client) GetProfilePictureInfo(ctx context.Context, jid types.JID, par
}
var pictureContent []waBinary.Node
if token, _ := cli.Store.PrivacyTokens.GetPrivacyToken(ctx, jid); token != nil {
if token, _ := cli.ensureTCToken(ctx, jid); token != nil {
pictureContent = []waBinary.Node{{
Tag: "tctoken",
Content: token.Token,
Content: token,
}}
}
@@ -730,9 +764,16 @@ func parseVerifiedNameContent(verifiedNameNode waBinary.Node) (*types.VerifiedNa
if err != nil {
return nil, err
}
ag := verifiedNameNode.AttrGetter()
return &types.VerifiedName{
Certificate: &cert,
Details: &certDetails,
VerifiedLevel: ag.String("verified_level"),
Version: ag.Int("v"),
HostStorage: ag.Int("host_storage"),
ActualActors: ag.Int("actual_actors"),
PrivacyModeTS: ag.UnixTime("privacy_mode_ts"),
}, nil
}
@@ -830,7 +871,8 @@ func (cli *Client) getFBIDDevices(ctx context.Context, jids []types.JID) ([]type
}
type UsyncQueryExtras struct {
BotListInfo []types.BotListInfo
BotListInfo []types.BotListInfo
IncludePrivacyToken bool
}
func (cli *Client) usync(ctx context.Context, jids []types.JID, mode, context string, query []waBinary.Node, extra ...UsyncQueryExtras) (*waBinary.Node, error) {
@@ -873,6 +915,16 @@ func (cli *Client) usync(ctx context.Context, jids []types.JID, mode, context st
Attrs: waBinary.Attrs{"persona_id": personaID},
}},
}}
} else if extras.IncludePrivacyToken {
token, err := cli.ensureTCToken(ctx, jid)
if err != nil {
cli.Log.Warnf("Failed to get privacy token for usync status query to %s: %v", jid, err)
} else if len(token) > 0 {
userList[i].Content = []waBinary.Node{{
Tag: "tctoken",
Content: token,
}}
}
}
default:
return nil, fmt.Errorf("unknown user server '%s'", jid.Server)
+14 -14
View File
@@ -15,20 +15,20 @@ import (
// Logger is a simple logger interface that can have subloggers for specific areas.
type Logger interface {
Warnf(msg string, args ...interface{})
Errorf(msg string, args ...interface{})
Infof(msg string, args ...interface{})
Debugf(msg string, args ...interface{})
Warnf(msg string, args ...any)
Errorf(msg string, args ...any)
Infof(msg string, args ...any)
Debugf(msg string, args ...any)
Sub(module string) Logger
}
type noopLogger struct{}
func (n *noopLogger) Errorf(_ string, _ ...interface{}) {}
func (n *noopLogger) Warnf(_ string, _ ...interface{}) {}
func (n *noopLogger) Infof(_ string, _ ...interface{}) {}
func (n *noopLogger) Debugf(_ string, _ ...interface{}) {}
func (n *noopLogger) Sub(_ string) Logger { return n }
func (n *noopLogger) Errorf(_ string, _ ...any) {}
func (n *noopLogger) Warnf(_ string, _ ...any) {}
func (n *noopLogger) Infof(_ string, _ ...any) {}
func (n *noopLogger) Debugf(_ string, _ ...any) {}
func (n *noopLogger) Sub(_ string) Logger { return n }
// Noop is a no-op Logger implementation that silently drops everything.
var Noop Logger = &noopLogger{}
@@ -53,7 +53,7 @@ var levelToInt = map[string]int{
"ERROR": 3,
}
func (s *stdoutLogger) outputf(level, msg string, args ...interface{}) {
func (s *stdoutLogger) outputf(level, msg string, args ...any) {
if levelToInt[level] < s.min {
return
}
@@ -65,10 +65,10 @@ func (s *stdoutLogger) outputf(level, msg string, args ...interface{}) {
fmt.Printf("%s%s [%s %s] %s%s\n", time.Now().Format("15:04:05.000"), colorStart, s.mod, level, fmt.Sprintf(msg, args...), colorReset)
}
func (s *stdoutLogger) Errorf(msg string, args ...interface{}) { s.outputf("ERROR", msg, args...) }
func (s *stdoutLogger) Warnf(msg string, args ...interface{}) { s.outputf("WARN", msg, args...) }
func (s *stdoutLogger) Infof(msg string, args ...interface{}) { s.outputf("INFO", msg, args...) }
func (s *stdoutLogger) Debugf(msg string, args ...interface{}) { s.outputf("DEBUG", msg, args...) }
func (s *stdoutLogger) Errorf(msg string, args ...any) { s.outputf("ERROR", msg, args...) }
func (s *stdoutLogger) Warnf(msg string, args ...any) { s.outputf("WARN", msg, args...) }
func (s *stdoutLogger) Infof(msg string, args ...any) { s.outputf("INFO", msg, args...) }
func (s *stdoutLogger) Debugf(msg string, args ...any) { s.outputf("DEBUG", msg, args...) }
func (s *stdoutLogger) Sub(mod string) Logger {
return &stdoutLogger{mod: fmt.Sprintf("%s/%s", s.mod, mod), color: s.color, min: s.min}
}