Skip to content

Commit 110210d

Browse files
Merge pull request #10 from evermos/oct-patch-version
feat: october patch version
2 parents 5ab97aa + 2769e67 commit 110210d

File tree

68 files changed

+6516
-10390
lines changed

Some content is hidden

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

68 files changed

+6516
-10390
lines changed

.pre-commit-config.yaml

+16-3
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,28 @@ repos:
44
hooks:
55
- id: trailing-whitespace
66
exclude_types: [markdown]
7-
exclude: LICENSE|def.proto
7+
exclude: LICENSE
88
- id: end-of-file-fixer
9-
exclude: LICENSE|def.proto
9+
exclude: LICENSE
1010
- id: check-yaml
1111
- id: check-added-large-files
1212

1313
- repo: https://github.com/tekwizely/pre-commit-golang
1414
rev: v1.0.0-rc.1
1515
hooks:
1616
- id: go-imports-repo
17-
args: ["-w"]
17+
args:
18+
- "-local"
19+
- "go.mau.fi/whatsmeow"
20+
- "-w"
1821
- id: go-vet-repo-mod
22+
# TODO enable this
23+
#- id: go-staticcheck-repo-mod
24+
- id: go-mod-tidy
25+
26+
- repo: https://github.com/beeper/pre-commit-go
27+
rev: v0.3.1
28+
hooks:
29+
# TODO enable this
30+
#- id: zerolog-ban-msgf
31+
- id: zerolog-use-stringer

appstate/encode.go

+30
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,36 @@ func BuildSettingPushName(pushName string) PatchInfo {
213213
}
214214
}
215215

216+
func newStarMutation(targetJID, senderJID string, messageID types.MessageID, fromMe string, starred bool) MutationInfo {
217+
return MutationInfo{
218+
Index: []string{IndexStar, targetJID, messageID, fromMe, senderJID},
219+
Version: 2,
220+
Value: &waProto.SyncActionValue{
221+
StarAction: &waProto.StarAction{
222+
Starred: &starred,
223+
},
224+
},
225+
}
226+
}
227+
228+
// BuildStar builds an app state patch for starring or unstarring a message.
229+
func BuildStar(target, sender types.JID, messageID types.MessageID, fromMe, starred bool) PatchInfo {
230+
isFromMe := "0"
231+
if fromMe {
232+
isFromMe = "1"
233+
}
234+
targetJID, senderJID := target.String(), sender.String()
235+
if target.User == sender.User {
236+
senderJID = "0"
237+
}
238+
return PatchInfo{
239+
Type: WAPatchRegularHigh,
240+
Mutations: []MutationInfo{
241+
newStarMutation(targetJID, senderJID, messageID, isFromMe, starred),
242+
},
243+
}
244+
}
245+
216246
func (proc *Processor) EncodePatch(keyID []byte, state HashState, patchInfo PatchInfo) ([]byte, error) {
217247
keys, err := proc.getAppStateKey(keyID)
218248
if err != nil {

broadcast.go

+1-6
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,7 @@ func (cli *Client) getBroadcastListParticipants(jid types.JID) ([]types.JID, err
3737
break
3838
}
3939
}
40-
if selfIndex >= 0 {
41-
if cli.DontSendSelfBroadcast {
42-
list[selfIndex] = list[len(list)-1]
43-
list = list[:len(list)-1]
44-
}
45-
} else if !cli.DontSendSelfBroadcast {
40+
if selfIndex < 0 {
4641
list = append(list, ownID)
4742
}
4843
return list, nil

call.go

+23
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,30 @@ func (cli *Client) handleCallEvent(node *waBinary.Node) {
8383
Reason: cag.String("reason"),
8484
Data: &child,
8585
})
86+
case "reject":
87+
cli.dispatchEvent(&events.CallReject{
88+
BasicCallMeta: basicMeta,
89+
Data: &child,
90+
})
8691
default:
8792
cli.dispatchEvent(&events.UnknownCallEvent{Node: node})
8893
}
8994
}
95+
96+
// RejectCall reject an incoming call.
97+
func (cli *Client) RejectCall(callFrom types.JID, callID string) error {
98+
ownID := cli.getOwnID()
99+
if ownID.IsEmpty() {
100+
return ErrNotLoggedIn
101+
}
102+
ownID, callFrom = ownID.ToNonAD(), callFrom.ToNonAD()
103+
return cli.sendNode(waBinary.Node{
104+
Tag: "call",
105+
Attrs: waBinary.Attrs{"id": cli.GenerateMessageID(), "from": ownID, "to": callFrom},
106+
Content: []waBinary.Node{{
107+
Tag: "reject",
108+
Attrs: waBinary.Attrs{"call-id": callID, "call-creator": callFrom, "count": "0"},
109+
Content: nil,
110+
}},
111+
})
112+
}

client.go

+11-10
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ import (
2626
"go.mau.fi/whatsmeow/appstate"
2727
waBinary "go.mau.fi/whatsmeow/binary"
2828
waProto "go.mau.fi/whatsmeow/binary/proto"
29+
"go.mau.fi/whatsmeow/proto/waE2E"
30+
"go.mau.fi/whatsmeow/proto/waWeb"
2931
"go.mau.fi/whatsmeow/socket"
3032
"go.mau.fi/whatsmeow/store"
3133
"go.mau.fi/whatsmeow/types"
@@ -156,10 +158,6 @@ type Client struct {
156158
// If false, decrypting a message from untrusted devices will fail.
157159
AutoTrustIdentity bool
158160

159-
// Should sending to own devices be skipped when sending broadcasts?
160-
// This works around a bug in the WhatsApp android app where it crashes if you send a status message from a linked device.
161-
DontSendSelfBroadcast bool
162-
163161
// Should SubscribePresence return an error if no privacy token is stored for the user?
164162
ErrorOnSubscribePresenceWithoutToken bool
165163

@@ -243,9 +241,8 @@ func NewClient(deviceStore *store.Device, log waLog.Logger) *Client {
243241

244242
pendingPhoneRerequests: make(map[types.MessageID]context.CancelFunc),
245243

246-
EnableAutoReconnect: true,
247-
AutoTrustIdentity: true,
248-
DontSendSelfBroadcast: true,
244+
EnableAutoReconnect: true,
245+
AutoTrustIdentity: true,
249246
}
250247
cli.nodeHandlers = map[string]nodeHandler{
251248
"message": cli.handleEncryptedMessage,
@@ -784,10 +781,10 @@ func (cli *Client) dispatchEvent(evt interface{}) {
784781
// evt, err := cli.ParseWebMessage(chatJID, historyMsg.GetMessage())
785782
// yourNormalEventHandler(evt)
786783
// }
787-
func (cli *Client) ParseWebMessage(chatJID types.JID, webMsg *waProto.WebMessageInfo) (*events.Message, error) {
784+
func (cli *Client) ParseWebMessage(chatJID types.JID, webMsg *waWeb.WebMessageInfo) (*events.Message, error) {
788785
var err error
789786
if chatJID.IsEmpty() {
790-
chatJID, err = types.ParseJID(webMsg.GetKey().GetRemoteJid())
787+
chatJID, err = types.ParseJID(webMsg.GetKey().GetRemoteJID())
791788
if err != nil {
792789
return nil, fmt.Errorf("no chat JID provided and failed to parse remote JID: %w", err)
793790
}
@@ -798,7 +795,7 @@ func (cli *Client) ParseWebMessage(chatJID types.JID, webMsg *waProto.WebMessage
798795
IsFromMe: webMsg.GetKey().GetFromMe(),
799796
IsGroup: chatJID.Server == types.GroupServer,
800797
},
801-
ID: webMsg.GetKey().GetId(),
798+
ID: webMsg.GetKey().GetID(),
802799
PushName: webMsg.GetPushName(),
803800
Timestamp: time.Unix(int64(webMsg.GetMessageTimestamp()), 0),
804801
}
@@ -825,6 +822,10 @@ func (cli *Client) ParseWebMessage(chatJID types.JID, webMsg *waProto.WebMessage
825822
Info: info,
826823
}
827824
evt.UnwrapRaw()
825+
if evt.Message.GetProtocolMessage().GetType() == waE2E.ProtocolMessage_MESSAGE_EDIT {
826+
evt.Info.ID = evt.Message.GetProtocolMessage().GetKey().GetID()
827+
evt.Message = evt.Message.GetProtocolMessage().GetEditedMessage()
828+
}
828829
return evt, nil
829830
}
830831

download-to-file.go

+8-4
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,15 @@ type File interface {
3838
//
3939
// This is otherwise identical to [Download], but writes the attachment to a file instead of returning it as a byte slice.
4040
func (cli *Client) DownloadToFile(msg DownloadableMessage, file File) error {
41-
mediaType, ok := classToMediaType[msg.ProtoReflect().Descriptor().Name()]
42-
if !ok {
43-
return fmt.Errorf("%w '%s'", ErrUnknownMediaType, string(msg.ProtoReflect().Descriptor().Name()))
41+
mediaType := GetMediaType(msg)
42+
if mediaType == "" {
43+
return fmt.Errorf("%w %T", ErrUnknownMediaType, msg)
4444
}
4545
urlable, ok := msg.(downloadableMessageWithURL)
4646
var url string
4747
var isWebWhatsappNetURL bool
4848
if ok {
49-
url = urlable.GetUrl()
49+
url = urlable.GetURL()
5050
isWebWhatsappNetURL = strings.HasPrefix(url, "https://web.whatsapp.net")
5151
}
5252
if len(url) > 0 && !isWebWhatsappNetURL {
@@ -132,6 +132,10 @@ func (cli *Client) downloadPossiblyEncryptedMediaWithRetriesToFile(url string, c
132132
retryDuration = retryafter.Parse(httpErr.Response.Header.Get("Retry-After"), retryDuration)
133133
}
134134
cli.Log.Warnf("Failed to download media due to network error: %v, retrying in %s...", err, retryDuration)
135+
_, err = file.Seek(0, io.SeekStart)
136+
if err != nil {
137+
return nil, fmt.Errorf("failed to seek to start of file to retry download: %w", err)
138+
}
135139
time.Sleep(retryDuration)
136140
}
137141
return

download.go

+18-7
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,16 @@ const (
5050
// All of the downloadable messages inside a Message struct implement this interface
5151
// (ImageMessage, VideoMessage, AudioMessage, DocumentMessage, StickerMessage).
5252
type DownloadableMessage interface {
53-
proto.Message
5453
GetDirectPath() string
5554
GetMediaKey() []byte
5655
GetFileSHA256() []byte
5756
GetFileEncSHA256() []byte
5857
}
5958

59+
type MediaTypeable interface {
60+
GetMediaType() MediaType
61+
}
62+
6063
// DownloadableThumbnail represents a protobuf message that contains a thumbnail attachment.
6164
//
6265
// This is primarily meant for link preview thumbnails in ExtendedTextMessage.
@@ -93,7 +96,7 @@ type downloadableMessageWithSizeBytes interface {
9396

9497
type downloadableMessageWithURL interface {
9598
DownloadableMessage
96-
GetUrl() string
99+
GetURL() string
97100
}
98101

99102
var classToMediaType = map[protoreflect.Name]MediaType{
@@ -175,7 +178,15 @@ func (cli *Client) DownloadThumbnail(msg DownloadableThumbnail) ([]byte, error)
175178

176179
// GetMediaType returns the MediaType value corresponding to the given protobuf message.
177180
func GetMediaType(msg DownloadableMessage) MediaType {
178-
return classToMediaType[msg.ProtoReflect().Descriptor().Name()]
181+
protoReflecter, ok := msg.(proto.Message)
182+
if !ok {
183+
mediaTypeable, ok := msg.(MediaTypeable)
184+
if !ok {
185+
return ""
186+
}
187+
return mediaTypeable.GetMediaType()
188+
}
189+
return classToMediaType[protoReflecter.ProtoReflect().Descriptor().Name()]
179190
}
180191

181192
// Download downloads the attachment from the given protobuf message.
@@ -188,15 +199,15 @@ func GetMediaType(msg DownloadableMessage) MediaType {
188199
//
189200
// You can also use DownloadAny to download the first non-nil sub-message.
190201
func (cli *Client) Download(msg DownloadableMessage) ([]byte, error) {
191-
mediaType, ok := classToMediaType[msg.ProtoReflect().Descriptor().Name()]
192-
if !ok {
193-
return nil, fmt.Errorf("%w '%s'", ErrUnknownMediaType, string(msg.ProtoReflect().Descriptor().Name()))
202+
mediaType := GetMediaType(msg)
203+
if mediaType == "" {
204+
return nil, fmt.Errorf("%w %T", ErrUnknownMediaType, msg)
194205
}
195206
urlable, ok := msg.(downloadableMessageWithURL)
196207
var url string
197208
var isWebWhatsappNetURL bool
198209
if ok {
199-
url = urlable.GetUrl()
210+
url = urlable.GetURL()
200211
isWebWhatsappNetURL = strings.HasPrefix(url, "https://web.whatsapp.net")
201212
}
202213
if len(url) > 0 && !isWebWhatsappNetURL {

go.mod

+7-5
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
11
module go.mau.fi/whatsmeow
22

3-
go 1.21
3+
go 1.22.0
4+
5+
toolchain go1.23.1
46

57
require (
68
github.com/google/uuid v1.6.0
79
github.com/gorilla/websocket v1.5.0
810
github.com/rs/zerolog v1.33.0
911
go.mau.fi/libsignal v0.1.1
10-
go.mau.fi/util v0.6.0
11-
golang.org/x/crypto v0.25.0
12-
golang.org/x/net v0.27.0
12+
go.mau.fi/util v0.8.0
13+
golang.org/x/crypto v0.27.0
14+
golang.org/x/net v0.29.0
1315
google.golang.org/protobuf v1.34.2
1416
)
1517

1618
require (
1719
filippo.io/edwards25519 v1.1.0 // indirect
1820
github.com/mattn/go-colorable v0.1.13 // indirect
1921
github.com/mattn/go-isatty v0.0.19 // indirect
20-
golang.org/x/sys v0.22.0 // indirect
22+
golang.org/x/sys v0.25.0 // indirect
2123
)

go.sum

+8-8
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,17 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT
2525
github.com/stretchr/testify v1.9.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.6.0 h1:W6SyB3Bm/GjenQ5iq8Z8WWdN85Gy2xS6L0wmnR7SVjg=
29-
go.mau.fi/util v0.6.0/go.mod h1:ljYdq3sPfpICc3zMU+/mHV/sa4z0nKxc67hSBwnrk8U=
30-
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
31-
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
32-
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
33-
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
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=
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.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
38-
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
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=
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=
4141
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=

0 commit comments

Comments
 (0)