1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
|
// Copyright (c) 2021 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 (
"errors"
"fmt"
waBinary "go.mau.fi/whatsmeow/binary"
)
// Miscellaneous errors
var (
ErrNoSession = errors.New("can't encrypt message for device: no signal session established")
ErrIQTimedOut = errors.New("info query timed out")
ErrNotConnected = errors.New("websocket not connected")
ErrNotLoggedIn = errors.New("the store doesn't contain a device JID")
ErrMessageTimedOut = errors.New("timed out waiting for message send response")
ErrAlreadyConnected = errors.New("websocket is already connected")
ErrQRAlreadyConnected = errors.New("GetQRChannel must be called before connecting")
ErrQRStoreContainsID = errors.New("GetQRChannel can only be called when there's no user ID in the client's Store")
ErrNoPushName = errors.New("can't send presence without PushName set")
)
var (
// ErrProfilePictureUnauthorized is returned by GetProfilePictureInfo when trying to get the profile picture of a user
// whose privacy settings prevent you from seeing their profile picture (status code 401).
ErrProfilePictureUnauthorized = errors.New("the user has hidden their profile picture from you")
// ErrProfilePictureNotSet is returned by GetProfilePictureInfo when the given user or group doesn't have a profile
// picture (status code 404).
ErrProfilePictureNotSet = errors.New("that user or group does not have a profile picture")
// ErrGroupInviteLinkUnauthorized is returned by GetGroupInviteLink if you don't have the permission to get the link (status code 401).
ErrGroupInviteLinkUnauthorized = errors.New("you don't have the permission to get the group's invite link")
// ErrNotInGroup is returned by group info getting methods if you're not in the group (status code 403).
ErrNotInGroup = errors.New("you're not participating in that group")
// ErrGroupNotFound is returned by group info getting methods if the group doesn't exist (status code 404).
ErrGroupNotFound = errors.New("that group does not exist")
// ErrInviteLinkInvalid is returned by methods that use group invite links if the invite link is malformed.
ErrInviteLinkInvalid = errors.New("that group invite link is not valid")
// ErrInviteLinkRevoked is returned by methods that use group invite links if the invite link was valid, but has been revoked and can no longer be used.
ErrInviteLinkRevoked = errors.New("that group invite link has been revoked")
// ErrBusinessMessageLinkNotFound is returned by ResolveBusinessMessageLink if the link doesn't exist or has been revoked.
ErrBusinessMessageLinkNotFound = errors.New("that business message link does not exist or has been revoked")
// ErrInvalidImageFormat is returned by SetGroupPhoto if the given photo is not in the correct format.
ErrInvalidImageFormat = errors.New("the given data is not a valid image")
// ErrMediaNotAvailableOnPhone is returned by DecryptMediaRetryNotification if the given event contains error code 2.
ErrMediaNotAvailableOnPhone = errors.New("media no longer available on phone")
// ErrUnknownMediaRetryError is returned by DecryptMediaRetryNotification if the given event contains an unknown error code.
ErrUnknownMediaRetryError = errors.New("unknown media retry error")
// ErrInvalidDisappearingTimer is returned by SetDisappearingTimer if the given timer is not one of the allowed values.
ErrInvalidDisappearingTimer = errors.New("invalid disappearing timer provided")
)
// Some errors that Client.SendMessage can return
var (
ErrBroadcastListUnsupported = errors.New("sending to non-status broadcast lists is not yet supported")
ErrUnknownServer = errors.New("can't send message to unknown server")
ErrRecipientADJID = errors.New("message recipient must be normal (non-AD) JID")
)
// Some errors that Client.Download can return
var (
ErrMediaDownloadFailedWith404 = errors.New("download failed with status code 404")
ErrMediaDownloadFailedWith410 = errors.New("download failed with status code 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")
)
type wrappedIQError struct {
HumanError error
IQError error
}
func (err *wrappedIQError) Error() string {
return err.HumanError.Error()
}
func (err *wrappedIQError) Is(other error) bool {
return errors.Is(other, err.HumanError)
}
func (err *wrappedIQError) Unwrap() error {
return err.IQError
}
func wrapIQError(human, iq error) error {
return &wrappedIQError{human, iq}
}
// IQError is a generic error container for info queries
type IQError struct {
Code int
Text string
ErrorNode *waBinary.Node
RawNode *waBinary.Node
}
// Common errors returned by info queries for use with errors.Is
var (
ErrIQBadRequest error = &IQError{Code: 400, Text: "bad-request"}
ErrIQNotAuthorized error = &IQError{Code: 401, Text: "not-authorized"}
ErrIQForbidden error = &IQError{Code: 403, Text: "forbidden"}
ErrIQNotFound error = &IQError{Code: 404, Text: "item-not-found"}
ErrIQNotAcceptable error = &IQError{Code: 406, Text: "not-acceptable"}
ErrIQGone error = &IQError{Code: 410, Text: "gone"}
)
func parseIQError(node *waBinary.Node) error {
var err IQError
err.RawNode = node
val, ok := node.GetOptionalChildByTag("error")
if ok {
err.ErrorNode = &val
ag := val.AttrGetter()
err.Code = ag.OptionalInt("code")
err.Text = ag.OptionalString("text")
}
return &err
}
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())
} else if iqe.RawNode != nil {
return fmt.Sprintf("info query returned unexpected response: %s", iqe.RawNode.XMLString())
} else {
return "unknown info query error"
}
}
return fmt.Sprintf("info query returned status %d: %s", iqe.Code, iqe.Text)
}
func (iqe *IQError) Is(other error) bool {
otherIQE, ok := other.(*IQError)
if !ok {
return false
} 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()
} else {
return false
}
}
// ElementMissingError is returned by various functions that parse XML elements when a required element is missing.
type ElementMissingError struct {
Tag string
In string
}
func (eme *ElementMissingError) Error() string {
return fmt.Sprintf("missing <%s> element in %s", eme.Tag, eme.In)
}
var ErrIQDisconnected = &DisconnectedError{Action: "info query"}
// DisconnectedError is returned if the websocket disconnects before an info query or other request gets a response.
type DisconnectedError struct {
Action string
Node *waBinary.Node
}
func (err *DisconnectedError) Error() string {
return fmt.Sprintf("websocket disconnected before %s returned response", err.Action)
}
func (err *DisconnectedError) Is(other error) bool {
otherDisc, ok := other.(*DisconnectedError)
if !ok {
return false
}
return otherDisc.Action == err.Action
}
|