Skip to content

Commit 566691d

Browse files
Merge pull request #13 from evermos/patch-jan
patch: january
2 parents f982441 + b93a6b7 commit 566691d

File tree

73 files changed

+13524
-10987
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+13524
-10987
lines changed

.github/ISSUE_TEMPLATE/issue.md

+7
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,10 @@ name: Open issue
33
about: For bug reports and feature requests directly related to whatsmeow
44

55
---
6+
7+
<!--
8+
Do not open issues for questions!
9+
Issues are only for bug reports and feature requests.
10+
11+
Questions belong in the Matrix room or on GitHub Discussions.
12+
-->

.github/workflows/go.yml

+7-7
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,17 @@ name: Go
22

33
on: [push, pull_request]
44

5+
env:
6+
GOTOOLCHAIN: local
7+
58
jobs:
69
build:
710
runs-on: ubuntu-latest
811
strategy:
912
fail-fast: false
1013
matrix:
11-
go-version: ["1.21", "1.22"]
12-
name: Build ${{ matrix.go-version == '1.22' && '(latest)' || '(old)' }}
14+
go-version: ["1.22", "1.23"]
15+
name: Build ${{ matrix.go-version == '1.23' && '(latest)' || '(old)' }}
1316

1417
steps:
1518
- uses: actions/checkout@v4
@@ -30,8 +33,5 @@ jobs:
3033
go install golang.org/x/tools/cmd/goimports@latest
3134
export PATH="$HOME/go/bin:$PATH"
3235
33-
- name: Install pre-commit
34-
run: pip install pre-commit
35-
36-
- name: Lint
37-
run: pre-commit run -a
36+
- name: Run pre-commit
37+
uses: pre-commit/[email protected]

.pre-commit-config.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
repos:
22
- repo: https://github.com/pre-commit/pre-commit-hooks
3-
rev: v4.4.0
3+
rev: v5.0.0
44
hooks:
55
- id: trailing-whitespace
66
exclude_types: [markdown]

appstate.go

+6
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ import (
2424
// FetchAppState fetches updates to the given type of app state. If fullSync is true, the current
2525
// cached state will be removed and all app state patches will be re-fetched from the server.
2626
func (cli *Client) FetchAppState(name appstate.WAPatchName, fullSync, onlyIfNotSynced bool) error {
27+
if cli == nil {
28+
return ErrClientIsNil
29+
}
2730
cli.appStateSyncLock.Lock()
2831
defer cli.appStateSyncLock.Unlock()
2932
if fullSync {
@@ -379,6 +382,9 @@ func (cli *Client) requestAppStateKeys(ctx context.Context, rawKeyIDs [][]byte)
379382
//
380383
// cli.SendAppState(appstate.BuildMute(targetJID, true, 24 * time.Hour))
381384
func (cli *Client) SendAppState(patch appstate.PatchInfo) error {
385+
if cli == nil {
386+
return ErrClientIsNil
387+
}
382388
version, hash, err := cli.Store.AppState.GetAppStateVersion(string(patch.Type))
383389
if err != nil {
384390
return err

binary/proto/legacy.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,7 @@ type (
451451
const (
452452
ADVEncryptionType_E2EE = waAdv.ADVEncryptionType_E2EE
453453
ADVEncryptionType_HOSTED = waAdv.ADVEncryptionType_HOSTED
454-
KeepType_UNKNOWN = waE2E.KeepType_UNKNOWN
454+
KeepType_UNKNOWN = waE2E.KeepType_UNKNOWN_KEEP_TYPE
455455
KeepType_KEEP_FOR_ALL = waE2E.KeepType_KEEP_FOR_ALL
456456
KeepType_UNDO_KEEP_FOR_ALL = waE2E.KeepType_UNDO_KEEP_FOR_ALL
457457
PeerDataOperationRequestType_UPLOAD_STICKER = waE2E.PeerDataOperationRequestType_UPLOAD_STICKER

client.go

+38-11
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ type Client struct {
6262
socket *socket.NoiseSocket
6363
socketLock sync.RWMutex
6464
socketWait chan struct{}
65+
wsDialer *websocket.Dialer
6566

6667
isLoggedIn atomic.Bool
6768
expectedDisconnect atomic.Bool
@@ -181,8 +182,9 @@ type Client struct {
181182
}
182183

183184
type MessengerConfig struct {
184-
UserAgent string
185-
BaseURL string
185+
UserAgent string
186+
BaseURL string
187+
WebsocketURL string
186188
}
187189

188190
// Size of buffer for the channel that all incoming XML nodes go through.
@@ -380,6 +382,9 @@ func (cli *Client) closeSocketWaitChan() {
380382
}
381383

382384
func (cli *Client) getOwnID() types.JID {
385+
if cli == nil {
386+
return types.EmptyJID
387+
}
383388
id := cli.Store.ID
384389
if id == nil {
385390
return types.EmptyJID
@@ -388,6 +393,9 @@ func (cli *Client) getOwnID() types.JID {
388393
}
389394

390395
func (cli *Client) WaitForConnection(timeout time.Duration) bool {
396+
if cli == nil {
397+
return false
398+
}
391399
timeoutChan := time.After(timeout)
392400
cli.socketLock.RLock()
393401
for cli.socket == nil || !cli.socket.IsConnected() || !cli.IsLoggedIn() {
@@ -404,9 +412,16 @@ func (cli *Client) WaitForConnection(timeout time.Duration) bool {
404412
return true
405413
}
406414

415+
func (cli *Client) SetWSDialer(dialer *websocket.Dialer) {
416+
cli.wsDialer = dialer
417+
}
418+
407419
// Connect connects the client to the WhatsApp web websocket. After connection, it will either
408420
// authenticate if there's data in the device store, or emit a QREvent to set up a new link.
409421
func (cli *Client) Connect() error {
422+
if cli == nil {
423+
return ErrClientIsNil
424+
}
410425
cli.socketLock.Lock()
411426
defer cli.socketLock.Unlock()
412427
if cli.socket != nil {
@@ -418,8 +433,10 @@ func (cli *Client) Connect() error {
418433
}
419434

420435
cli.resetExpectedDisconnect()
421-
wsDialer := websocket.Dialer{}
422-
if !cli.proxyOnlyLogin || cli.Store.ID == nil {
436+
var wsDialer websocket.Dialer
437+
if cli.wsDialer != nil {
438+
wsDialer = *cli.wsDialer
439+
} else if !cli.proxyOnlyLogin || cli.Store.ID == nil {
423440
if cli.proxy != nil {
424441
wsDialer.Proxy = cli.proxy
425442
} else if cli.socksProxy != nil {
@@ -432,12 +449,14 @@ func (cli *Client) Connect() error {
432449
}
433450
fs := socket.NewFrameSocket(cli.Log.Sub("Socket"), wsDialer)
434451
if cli.MessengerConfig != nil {
435-
fs.URL = "wss://web-chat-e2ee.facebook.com/ws/chat"
452+
fs.URL = cli.MessengerConfig.WebsocketURL
436453
fs.HTTPHeaders.Set("Origin", cli.MessengerConfig.BaseURL)
437454
fs.HTTPHeaders.Set("User-Agent", cli.MessengerConfig.UserAgent)
438-
fs.HTTPHeaders.Set("Sec-Fetch-Dest", "empty")
439-
fs.HTTPHeaders.Set("Sec-Fetch-Mode", "websocket")
440-
fs.HTTPHeaders.Set("Sec-Fetch-Site", "cross-site")
455+
fs.HTTPHeaders.Set("Cache-Control", "no-cache")
456+
fs.HTTPHeaders.Set("Pragma", "no-cache")
457+
//fs.HTTPHeaders.Set("Sec-Fetch-Dest", "empty")
458+
//fs.HTTPHeaders.Set("Sec-Fetch-Mode", "websocket")
459+
//fs.HTTPHeaders.Set("Sec-Fetch-Site", "cross-site")
441460
}
442461
if err := fs.Connect(); err != nil {
443462
fs.Close(0)
@@ -453,7 +472,7 @@ func (cli *Client) Connect() error {
453472

454473
// IsLoggedIn returns true after the client is successfully connected and authenticated on WhatsApp.
455474
func (cli *Client) IsLoggedIn() bool {
456-
return cli.isLoggedIn.Load()
475+
return cli != nil && cli.isLoggedIn.Load()
457476
}
458477

459478
func (cli *Client) onDisconnect(ns *socket.NoiseSocket, remote bool) {
@@ -517,6 +536,9 @@ func (cli *Client) autoReconnect() {
517536
// IsConnected checks if the client is connected to the WhatsApp web websocket.
518537
// Note that this doesn't check if the client is authenticated. See the IsLoggedIn field for that.
519538
func (cli *Client) IsConnected() bool {
539+
if cli == nil {
540+
return false
541+
}
520542
cli.socketLock.RLock()
521543
connected := cli.socket != nil && cli.socket.IsConnected()
522544
cli.socketLock.RUnlock()
@@ -528,7 +550,7 @@ func (cli *Client) IsConnected() bool {
528550
// This will not emit any events, the Disconnected event is only used when the
529551
// connection is closed by the server or a network error.
530552
func (cli *Client) Disconnect() {
531-
if cli.socket == nil {
553+
if cli == nil || cli.socket == nil {
532554
return
533555
}
534556
cli.socketLock.Lock()
@@ -553,7 +575,9 @@ func (cli *Client) unlockedDisconnect() {
553575
// Note that this will not emit any events. The LoggedOut event is only used for external logouts
554576
// (triggered by the user from the main device or by WhatsApp servers).
555577
func (cli *Client) Logout() error {
556-
if cli.MessengerConfig != nil {
578+
if cli == nil {
579+
return ErrClientIsNil
580+
} else if cli.MessengerConfig != nil {
557581
return errors.New("can't logout with Messenger credentials")
558582
}
559583
ownID := cli.getOwnID()
@@ -737,6 +761,9 @@ func (cli *Client) handlerQueueLoop(ctx context.Context) {
737761
}
738762

739763
func (cli *Client) sendNodeAndGetData(node waBinary.Node) ([]byte, error) {
764+
if cli == nil {
765+
return nil, ErrClientIsNil
766+
}
740767
cli.socketLock.RLock()
741768
sock := cli.socket
742769
cli.socketLock.RUnlock()

download-to-file.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,12 @@ func (cli *Client) DownloadMediaWithPathToFile(directPath string, encFileHash, f
7777
// TODO omit hash for unencrypted media?
7878
mediaURL := fmt.Sprintf("https://%s%s&hash=%s&mms-type=%s&__wa-mms=", host.Hostname, directPath, base64.URLEncoding.EncodeToString(encFileHash), mmsType)
7979
err = cli.downloadAndDecryptToFile(mediaURL, mediaKey, mediaType, fileLength, encFileHash, fileHash, file)
80-
if err == nil || errors.Is(err, ErrFileLengthMismatch) || errors.Is(err, ErrInvalidMediaSHA256) {
80+
if err == nil || errors.Is(err, ErrFileLengthMismatch) || errors.Is(err, ErrInvalidMediaSHA256) ||
81+
errors.Is(err, ErrMediaDownloadFailedWith403) || errors.Is(err, ErrMediaDownloadFailedWith404) || errors.Is(err, ErrMediaDownloadFailedWith410) {
8182
return err
8283
} else if i >= len(mediaConn.Hosts)-1 {
8384
return fmt.Errorf("failed to download media from last host: %w", err)
8485
}
85-
// TODO there are probably some errors that shouldn't retry
8686
cli.Log.Warnf("Failed to download media: %s, trying with next host...", err)
8787
}
8888
return err

download.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -240,12 +240,12 @@ func (cli *Client) DownloadMediaWithPath(directPath string, encFileHash, fileHas
240240
// TODO omit hash for unencrypted media?
241241
mediaURL := fmt.Sprintf("https://%s%s&hash=%s&mms-type=%s&__wa-mms=", host.Hostname, directPath, base64.URLEncoding.EncodeToString(encFileHash), mmsType)
242242
data, err = cli.downloadAndDecrypt(mediaURL, mediaKey, mediaType, fileLength, encFileHash, fileHash)
243-
if err == nil || errors.Is(err, ErrFileLengthMismatch) || errors.Is(err, ErrInvalidMediaSHA256) {
243+
if err == nil || errors.Is(err, ErrFileLengthMismatch) || errors.Is(err, ErrInvalidMediaSHA256) ||
244+
errors.Is(err, ErrMediaDownloadFailedWith403) || errors.Is(err, ErrMediaDownloadFailedWith404) || errors.Is(err, ErrMediaDownloadFailedWith410) {
244245
return
245246
} else if i >= len(mediaConn.Hosts)-1 {
246247
return nil, fmt.Errorf("failed to download media from last host: %w", err)
247248
}
248-
// TODO there are probably some errors that shouldn't retry
249249
cli.Log.Warnf("Failed to download media: %s, trying with next host...", err)
250250
}
251251
return

errors.go

+2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616

1717
// Miscellaneous errors
1818
var (
19+
ErrClientIsNil = errors.New("client is nil")
1920
ErrNoSession = errors.New("can't encrypt message for device: no signal session established")
2021
ErrIQTimedOut = errors.New("info query timed out")
2122
ErrNotConnected = errors.New("websocket not connected")
@@ -183,6 +184,7 @@ var (
183184
ErrIQGone error = &IQError{Code: 410, Text: "gone"}
184185
ErrIQResourceLimit error = &IQError{Code: 419, Text: "resource-limit"}
185186
ErrIQLocked error = &IQError{Code: 423, Text: "locked"}
187+
ErrIQRateOverLimit error = &IQError{Code: 429, Text: "rate-overlimit"}
186188
ErrIQInternalServerError error = &IQError{Code: 500, Text: "internal-server-error"}
187189
ErrIQServiceUnavailable error = &IQError{Code: 503, Text: "service-unavailable"}
188190
ErrIQPartialServerError error = &IQError{Code: 530, Text: "partial-server-error"}

go.mod

+6-6
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,22 @@ module go.mau.fi/whatsmeow
22

33
go 1.22.0
44

5-
toolchain go1.23.1
5+
toolchain go1.23.4
66

77
require (
88
github.com/google/uuid v1.6.0
99
github.com/gorilla/websocket v1.5.0
1010
github.com/rs/zerolog v1.33.0
1111
go.mau.fi/libsignal v0.1.1
12-
go.mau.fi/util v0.8.0
13-
golang.org/x/crypto v0.27.0
14-
golang.org/x/net v0.29.0
15-
google.golang.org/protobuf v1.34.2
12+
go.mau.fi/util v0.8.3
13+
golang.org/x/crypto v0.31.0
14+
golang.org/x/net v0.33.0
15+
google.golang.org/protobuf v1.36.1
1616
)
1717

1818
require (
1919
filippo.io/edwards25519 v1.1.0 // indirect
2020
github.com/mattn/go-colorable v0.1.13 // indirect
2121
github.com/mattn/go-isatty v0.0.19 // indirect
22-
golang.org/x/sys v0.25.0 // indirect
22+
golang.org/x/sys v0.28.0 // indirect
2323
)

go.sum

+12-12
Original file line numberDiff line numberDiff line change
@@ -21,24 +21,24 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
2121
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
2222
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
2323
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
24-
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
25-
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
24+
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
25+
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
2626
go.mau.fi/libsignal v0.1.1 h1:m/0PGBh4QKP/I1MQ44ti4C0fMbLMuHb95cmDw01FIpI=
2727
go.mau.fi/libsignal v0.1.1/go.mod h1:QLs89F/OA3ThdSL2Wz2p+o+fi8uuQUz0e1BRa6ExdBw=
28-
go.mau.fi/util v0.8.0 h1:MiSny8jgQq4XtCLAT64gDJhZVhqiDeMVIEBDFVw+M0g=
29-
go.mau.fi/util v0.8.0/go.mod h1:1Ixb8HWoVbl3rT6nAX6nV4iMkzn7KU/KXwE0Rn5RmsQ=
30-
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
31-
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
32-
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
33-
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
28+
go.mau.fi/util v0.8.3 h1:sulhXtfquMrQjsOP67x9CzWVBYUwhYeoo8hNQIpCWZ4=
29+
go.mau.fi/util v0.8.3/go.mod h1:c00Db8xog70JeIsEvhdHooylTkTkakgnAOsZ04hplQY=
30+
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
31+
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
32+
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
33+
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
3434
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
3535
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
3636
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
37-
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
38-
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
37+
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
38+
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
3939
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
4040
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
41-
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
42-
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
41+
google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk=
42+
google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
4343
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
4444
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

mediaconn.go

+3
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ func (mc *MediaConn) Expiry() time.Time {
4141
}
4242

4343
func (cli *Client) refreshMediaConn(force bool) (*MediaConn, error) {
44+
if cli == nil {
45+
return nil, ErrClientIsNil
46+
}
4447
cli.mediaConnLock.Lock()
4548
defer cli.mediaConnLock.Unlock()
4649
if cli.mediaConnCache == nil || force || time.Now().After(cli.mediaConnCache.Expiry()) {

message.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -219,10 +219,12 @@ func (cli *Client) handlePlaintextMessage(info *types.MessageInfo, node *waBinar
219219
}
220220

221221
func (cli *Client) decryptMessages(info *types.MessageInfo, node *waBinary.Node) {
222-
if len(node.GetChildrenByTag("unavailable")) > 0 && len(node.GetChildrenByTag("enc")) == 0 {
223-
cli.Log.Warnf("Unavailable message %s from %s", info.ID, info.SourceString())
222+
unavailableNode, ok := node.GetOptionalChildByTag("unavailable")
223+
if ok && len(node.GetChildrenByTag("enc")) == 0 {
224+
uType := events.UnavailableType(unavailableNode.AttrGetter().String("type"))
225+
cli.Log.Warnf("Unavailable message %s from %s (type: %q)", info.ID, info.SourceString(), uType)
224226
go cli.delayedRequestMessageFromPhone(info)
225-
cli.dispatchEvent(&events.UndecryptableMessage{Info: *info, IsUnavailable: true})
227+
cli.dispatchEvent(&events.UndecryptableMessage{Info: *info, IsUnavailable: true, UnavailableType: uType})
226228
return
227229
}
228230

msgsecret.go

+6
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ type messageEncryptedSecret interface {
8383
}
8484

8585
func (cli *Client) decryptMsgSecret(msg *events.Message, useCase MsgSecretType, encrypted messageEncryptedSecret, origMsgKey *waCommon.MessageKey) ([]byte, error) {
86+
if cli == nil {
87+
return nil, ErrClientIsNil
88+
}
8689
pollSender, err := getOrigSenderFromKey(msg, origMsgKey)
8790
if err != nil {
8891
return nil, err
@@ -102,6 +105,9 @@ func (cli *Client) decryptMsgSecret(msg *events.Message, useCase MsgSecretType,
102105
}
103106

104107
func (cli *Client) encryptMsgSecret(chat, origSender types.JID, origMsgID types.MessageID, useCase MsgSecretType, plaintext []byte) (ciphertext, iv []byte, err error) {
108+
if cli == nil {
109+
return nil, nil, ErrClientIsNil
110+
}
105111
ownID := cli.getOwnID()
106112
if ownID.IsEmpty() {
107113
return nil, nil, ErrNotLoggedIn

newsletter.go

+3
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ func (cli *Client) NewsletterSubscribeLiveUpdates(ctx context.Context, jid types
4040
//
4141
// This is not the same as marking the channel as read on your other devices, use the usual MarkRead function for that.
4242
func (cli *Client) NewsletterMarkViewed(jid types.JID, serverIDs []types.MessageServerID) error {
43+
if cli == nil {
44+
return ErrClientIsNil
45+
}
4346
items := make([]waBinary.Node, len(serverIDs))
4447
for i, id := range serverIDs {
4548
items[i] = waBinary.Node{

pair-code.go

+3
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,9 @@ func generateCompanionEphemeralKey() (ephemeralKeyPair *keys.KeyPair, ephemeralK
8787
//
8888
// See https://faq.whatsapp.com/1324084875126592 for more info
8989
func (cli *Client) PairPhone(phone string, showPushNotification bool, clientType PairClientType, clientDisplayName string) (string, error) {
90+
if cli == nil {
91+
return "", ErrClientIsNil
92+
}
9093
ephemeralKeyPair, ephemeralKey, encodedLinkingCode := generateCompanionEphemeralKey()
9194
phone = notNumbers.ReplaceAllString(phone, "")
9295
if len(phone) <= 6 {

0 commit comments

Comments
 (0)