Update whatsmeow for WhatsApp web version 2.3000.x

This commit is contained in:
Tulir Asokan 2024-05-22 19:30:59 +03:00
parent 00a9b0b783
commit 73266af075
7 changed files with 102 additions and 122 deletions

10
go.mod
View file

@ -8,18 +8,18 @@ require (
github.com/gorilla/websocket v1.5.0
github.com/lib/pq v1.10.9
github.com/mattn/go-sqlite3 v1.14.22
github.com/prometheus/client_golang v1.19.0
github.com/rs/zerolog v1.32.0
github.com/prometheus/client_golang v1.19.1
github.com/rs/zerolog v1.33.0
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
github.com/tidwall/gjson v1.17.1
go.mau.fi/util v0.4.2
go.mau.fi/webp v0.1.0
go.mau.fi/whatsmeow v0.0.0-20240520180327-81f8f07f1dfb
go.mau.fi/whatsmeow v0.0.0-20240603101645-64bc969fbe78
golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8
golang.org/x/image v0.15.0
golang.org/x/image v0.16.0
golang.org/x/net v0.25.0
golang.org/x/sync v0.7.0
google.golang.org/protobuf v1.33.0
google.golang.org/protobuf v1.34.1
maunium.net/go/mautrix v0.18.1
)

20
go.sum
View file

@ -38,8 +38,8 @@ github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxU
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
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/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU=
github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k=
github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE=
@ -50,8 +50,8 @@ github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjR
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc=
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0=
github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
@ -73,16 +73,16 @@ go.mau.fi/util v0.4.2 h1:RR3TOcRHmCF9Bx/3YG4S65MYfa+nV6/rn8qBWW4Mi30=
go.mau.fi/util v0.4.2/go.mod h1:PlAVfUUcPyHPrwnvjkJM9UFcPE7qGPDJqk+Oufa1Gtw=
go.mau.fi/webp v0.1.0 h1:BHObH/DcFntT9KYun5pDr0Ot4eUZO8k2C7eP7vF4ueA=
go.mau.fi/webp v0.1.0/go.mod h1:e42Z+VMFrUMS9cpEwGRIor+lQWO8oUAyPyMtcL+NMt8=
go.mau.fi/whatsmeow v0.0.0-20240520180327-81f8f07f1dfb h1:FW5W0ewNOmunylB3Pmru8PvxYkhI6ZphCJtimM2aB6o=
go.mau.fi/whatsmeow v0.0.0-20240520180327-81f8f07f1dfb/go.mod h1:0+65CYaE6r4dWzr0dN8i+UZKy0gIfJ79VuSqIl0nKRM=
go.mau.fi/whatsmeow v0.0.0-20240603101645-64bc969fbe78 h1:zST/E2cOjQEjXuis0miwSd20Uf+ffdJna6QefQyxEcc=
go.mau.fi/whatsmeow v0.0.0-20240603101645-64bc969fbe78/go.mod h1:0+65CYaE6r4dWzr0dN8i+UZKy0gIfJ79VuSqIl0nKRM=
go.mau.fi/zeroconfig v0.1.2 h1:DKOydWnhPMn65GbXZOafgkPm11BvFashZWLct0dGFto=
go.mau.fi/zeroconfig v0.1.2/go.mod h1:NcSJkf180JT+1IId76PcMuLTNa1CzsFFZ0nBygIQM70=
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8 h1:ESSUROHIBHg7USnszlcdmjBEwdMj9VUvU+OPk4yl2mc=
golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI=
golang.org/x/image v0.15.0 h1:kOELfmgrmJlw4Cdb7g/QGuB3CvDrXbqEIww/pNtNBm8=
golang.org/x/image v0.15.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE=
golang.org/x/image v0.16.0 h1:9kloLAKhUufZhA12l5fwnx2NZW39/we1UhBesW433jw=
golang.org/x/image v0.16.0/go.mod h1:ugSZItdV4nOxyqp56HmXwH0Ry0nBCpjnZdpDaIHdoPs=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
@ -94,8 +94,8 @@ golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=

View file

@ -953,7 +953,7 @@ func (portal *Portal) wrapBatchReaction(ctx context.Context, source *User, react
Key: variationselector.Add(reaction.GetText()),
},
}
if rawTS := reaction.GetSenderTimestampMs(); rawTS >= mainEventTS.UnixMilli() && rawTS <= time.Now().UnixMilli() {
if rawTS := reaction.GetSenderTimestampMS(); rawTS >= mainEventTS.UnixMilli() && rawTS <= time.Now().UnixMilli() {
reactionInfo.Timestamp = time.UnixMilli(rawTS)
}
wrappedContent := event.Content{Parsed: &content}

47
main.go
View file

@ -19,7 +19,6 @@ package main
import (
"context"
_ "embed"
"net/http"
"net/url"
"os"
"strconv"
@ -28,6 +27,7 @@ import (
"time"
"github.com/rs/zerolog"
"go.mau.fi/whatsmeow/proto/waCompanionReg"
waLog "go.mau.fi/whatsmeow/util/log"
"google.golang.org/protobuf/proto"
@ -140,7 +140,7 @@ func (br *WABridge) Init() {
store.DeviceProps.Version.Secondary = proto.Uint32(uint32(secondary))
store.DeviceProps.Version.Tertiary = proto.Uint32(uint32(tertiary))
}
platformID, ok := waProto.DeviceProps_PlatformType_value[strings.ToUpper(br.Config.WhatsApp.BrowserName)]
platformID, ok := waCompanionReg.DeviceProps_PlatformType_value[strings.ToUpper(br.Config.WhatsApp.BrowserName)]
if ok {
store.DeviceProps.PlatformType = waProto.DeviceProps_PlatformType(platformID).Enum()
}
@ -155,7 +155,17 @@ func (br *WABridge) Start() {
if br.Provisioning != nil {
br.Provisioning.Init()
}
go br.CheckWhatsAppUpdate()
// TODO find out how the new whatsapp version checks for updates
ver, err := whatsmeow.GetLatestVersion(br.AS.HTTPClient)
if err != nil {
br.ZLog.Err(err).Msg("Failed to get latest WhatsApp web version number")
} else {
br.ZLog.Debug().
Stringer("hardcoded_version", store.GetWAVersion()).
Stringer("latest_version", *ver).
Msg("Got latest WhatsApp web version number")
store.SetWAVersion(*ver)
}
br.WaitWebsocketConnected()
go br.StartUsers()
if br.Config.Metrics.Enabled {
@ -165,37 +175,6 @@ func (br *WABridge) Start() {
go br.Loop()
}
func (br *WABridge) CheckWhatsAppUpdate() {
br.ZLog.Debug().Msg("Checking for WhatsApp web update")
resp, err := whatsmeow.CheckUpdate(http.DefaultClient)
if err != nil {
br.ZLog.Warn().Err(err).Msg("Failed to check for WhatsApp web update")
return
}
if store.GetWAVersion() == resp.ParsedVersion {
br.ZLog.Debug().Msg("Bridge is using latest WhatsApp web protocol")
} else if store.GetWAVersion().LessThan(resp.ParsedVersion) {
if resp.IsBelowHard || resp.IsBroken {
br.ZLog.Warn().
Stringer("latest_version", resp.ParsedVersion).
Stringer("current_version", store.GetWAVersion()).
Msg("Bridge is using outdated WhatsApp web protocol and probably doesn't work anymore")
} else if resp.IsBelowSoft {
br.ZLog.Info().
Stringer("latest_version", resp.ParsedVersion).
Stringer("current_version", store.GetWAVersion()).
Msg("Bridge is using outdated WhatsApp web protocol")
} else {
br.ZLog.Debug().
Stringer("latest_version", resp.ParsedVersion).
Stringer("current_version", store.GetWAVersion()).
Msg("Bridge is using outdated WhatsApp web protocol")
}
} else {
br.ZLog.Debug().Msg("Bridge is using newer than latest WhatsApp web protocol")
}
}
func (br *WABridge) Loop() {
ctx := br.ZLog.With().Str("action", "background loop").Logger().WithContext(context.TODO())
for {

127
portal.go
View file

@ -48,6 +48,7 @@ import (
cwebp "go.mau.fi/webp"
"go.mau.fi/whatsmeow"
waProto "go.mau.fi/whatsmeow/binary/proto"
"go.mau.fi/whatsmeow/proto/waMmsRetry"
"go.mau.fi/whatsmeow/types"
"go.mau.fi/whatsmeow/types/events"
"golang.org/x/exp/slices"
@ -751,7 +752,7 @@ func (portal *Portal) convertMessage(ctx context.Context, intent *appservice.Int
return portal.convertMediaMessage(ctx, intent, source, info, waMsg.GetPtvMessage(), "video message", isBackfill)
case waMsg.AudioMessage != nil:
typeName := "audio attachment"
if waMsg.GetAudioMessage().GetPtt() {
if waMsg.GetAudioMessage().GetPTT() {
typeName = "voice message"
}
return portal.convertMediaMessage(ctx, intent, source, info, waMsg.GetAudioMessage(), typeName, isBackfill)
@ -2696,13 +2697,13 @@ func (r ReplyInfo) MarshalZerologObject(e *zerolog.Event) {
}
type Replyable interface {
GetStanzaId() string
GetStanzaID() string
GetParticipant() string
GetRemoteJid() string
}
func GetReply(replyable Replyable) *ReplyInfo {
if replyable.GetStanzaId() == "" {
if replyable.GetStanzaID() == "" {
return nil
}
sender, err := types.ParseJID(replyable.GetParticipant())
@ -2711,7 +2712,7 @@ func GetReply(replyable Replyable) *ReplyInfo {
}
chat, _ := types.ParseJID(replyable.GetRemoteJid())
return &ReplyInfo{
MessageID: types.MessageID(replyable.GetStanzaId()),
MessageID: types.MessageID(replyable.GetStanzaID()),
Chat: chat,
Sender: sender,
}
@ -2759,7 +2760,7 @@ func (portal *Portal) convertTextMessage(ctx context.Context, intent *appservice
}
contextInfo := msg.GetExtendedTextMessage().GetContextInfo()
portal.bridge.Formatter.ParseWhatsApp(ctx, portal.MXID, content, contextInfo.GetMentionedJid(), false, false)
portal.bridge.Formatter.ParseWhatsApp(ctx, portal.MXID, content, contextInfo.GetMentionedJID(), false, false)
expiresIn := time.Duration(contextInfo.GetExpiration()) * time.Second
extraAttrs := map[string]interface{}{}
extraAttrs["com.beeper.linkpreviews"] = portal.convertURLPreviewToBeeper(ctx, intent, source, msg.GetExtendedTextMessage())
@ -2800,7 +2801,7 @@ func (portal *Portal) convertTemplateMessage(ctx context.Context, intent *appser
descriptions[i] = fmt.Sprintf("<%s>", button.QuickReplyButton.GetDisplayText())
addButtonText = true
case *waProto.HydratedTemplateButton_UrlButton:
descriptions[i] = fmt.Sprintf("[%s](%s)", button.UrlButton.GetDisplayText(), button.UrlButton.GetUrl())
descriptions[i] = fmt.Sprintf("[%s](%s)", button.UrlButton.GetDisplayText(), button.UrlButton.GetURL())
case *waProto.HydratedTemplateButton_CallButton:
descriptions[i] = fmt.Sprintf("[%s](tel:%s)", button.CallButton.GetDisplayText(), button.CallButton.GetPhoneNumber())
}
@ -2841,7 +2842,7 @@ func (portal *Portal) convertTemplateMessage(ctx context.Context, intent *appser
if converted.Extra == nil {
converted.Extra = make(map[string]interface{})
}
converted.Extra["fi.mau.whatsapp.hydrated_template_id"] = tpl.GetTemplateId()
converted.Extra["fi.mau.whatsapp.hydrated_template_id"] = tpl.GetTemplateID()
return converted
}
@ -2855,7 +2856,7 @@ func (portal *Portal) convertTemplateButtonReplyMessage(ctx context.Context, int
},
Extra: map[string]interface{}{
"fi.mau.whatsapp.template_button_reply": map[string]interface{}{
"id": msg.GetSelectedId(),
"id": msg.GetSelectedID(),
"index": msg.GetSelectedIndex(),
},
},
@ -2936,7 +2937,7 @@ func (portal *Portal) convertListResponseMessage(ctx context.Context, intent *ap
},
Extra: map[string]interface{}{
"fi.mau.whatsapp.list_reply": map[string]interface{}{
"row_id": msg.GetSingleSelectReply().GetSelectedRowId(),
"row_id": msg.GetSingleSelectReply().GetSelectedRowID(),
},
},
ReplyTo: GetReply(msg.GetContextInfo()),
@ -3116,7 +3117,7 @@ func (portal *Portal) convertLiveLocationMessage(ctx context.Context, intent *ap
}
func (portal *Portal) convertLocationMessage(ctx context.Context, intent *appservice.IntentAPI, msg *waProto.LocationMessage) *ConvertedMessage {
url := msg.GetUrl()
url := msg.GetURL()
if len(url) == 0 {
url = fmt.Sprintf("https://maps.google.com/?q=%.5f,%.5f", msg.GetDegreesLatitude(), msg.GetDegreesLongitude())
}
@ -3141,14 +3142,14 @@ func (portal *Portal) convertLocationMessage(ctx context.Context, intent *appser
GeoURI: fmt.Sprintf("geo:%.5f,%.5f", msg.GetDegreesLatitude(), msg.GetDegreesLongitude()),
}
if len(msg.GetJpegThumbnail()) > 0 {
thumbnailMime := http.DetectContentType(msg.GetJpegThumbnail())
uploadedThumbnail, _ := intent.UploadBytes(ctx, msg.GetJpegThumbnail(), thumbnailMime)
if len(msg.GetJPEGThumbnail()) > 0 {
thumbnailMime := http.DetectContentType(msg.GetJPEGThumbnail())
uploadedThumbnail, _ := intent.UploadBytes(ctx, msg.GetJPEGThumbnail(), thumbnailMime)
if uploadedThumbnail != nil {
cfg, _, _ := image.DecodeConfig(bytes.NewReader(msg.GetJpegThumbnail()))
cfg, _, _ := image.DecodeConfig(bytes.NewReader(msg.GetJPEGThumbnail()))
content.Info = &event.FileInfo{
ThumbnailInfo: &event.FileInfo{
Size: len(msg.GetJpegThumbnail()),
Size: len(msg.GetJPEGThumbnail()),
Width: cfg.Width,
Height: cfg.Height,
MimeType: thumbnailMime,
@ -3183,9 +3184,9 @@ func (portal *Portal) convertGroupInviteMessage(ctx context.Context, intent *app
expiry := time.Unix(msg.GetInviteExpiration(), 0)
template := inviteMsg
var extraAttrs map[string]any
groupJID, err := types.ParseJID(msg.GetGroupJid())
groupJID, err := types.ParseJID(msg.GetGroupJID())
if err != nil {
zerolog.Ctx(ctx).Err(err).Str("invite_group_jid", msg.GetGroupJid()).Msg("Failed to parse invite group JID")
zerolog.Ctx(ctx).Err(err).Str("invite_group_jid", msg.GetGroupJID()).Msg("Failed to parse invite group JID")
template = inviteMsgBroken
} else {
extraAttrs = map[string]interface{}{
@ -3457,7 +3458,7 @@ type MediaMessage interface {
type MediaMessageWithThumbnail interface {
MediaMessage
GetJpegThumbnail() []byte
GetJPEGThumbnail() []byte
}
type MediaMessageWithCaption interface {
@ -3532,8 +3533,8 @@ func (portal *Portal) convertMediaMessageContent(ctx context.Context, intent *ap
}
messageWithThumbnail, ok := msg.(MediaMessageWithThumbnail)
if ok && messageWithThumbnail.GetJpegThumbnail() != nil && (portal.bridge.Config.Bridge.WhatsappThumbnail || isGIF) {
thumbnailData := messageWithThumbnail.GetJpegThumbnail()
if ok && messageWithThumbnail.GetJPEGThumbnail() != nil && (portal.bridge.Config.Bridge.WhatsappThumbnail || isGIF) {
thumbnailData := messageWithThumbnail.GetJPEGThumbnail()
thumbnailMime := http.DetectContentType(thumbnailData)
thumbnailCfg, _, _ := image.DecodeConfig(bytes.NewReader(thumbnailData))
thumbnailSize := len(thumbnailData)
@ -3611,7 +3612,7 @@ func (portal *Portal) convertMediaMessageContent(ctx context.Context, intent *ap
"duration": int(audioMessage.GetSeconds()) * 1000,
"waveform": waveform,
}
if audioMessage.GetPtt() || audioMessage.GetMimetype() == "audio/ogg; codecs/opus" {
if audioMessage.GetPTT() || audioMessage.GetMimetype() == "audio/ogg; codecs/opus" {
extraContent["org.matrix.msc3245.voice"] = map[string]interface{}{}
}
}
@ -3624,7 +3625,7 @@ func (portal *Portal) convertMediaMessageContent(ctx context.Context, intent *ap
MsgType: event.MsgNotice,
}
portal.bridge.Formatter.ParseWhatsApp(ctx, portal.MXID, captionContent, msg.GetContextInfo().GetMentionedJid(), false, false)
portal.bridge.Formatter.ParseWhatsApp(ctx, portal.MXID, captionContent, msg.GetContextInfo().GetMentionedJID(), false, false)
}
return &ConvertedMessage{
@ -3707,8 +3708,8 @@ func (portal *Portal) convertMediaMessage(ctx context.Context, intent *appservic
Key: msg.GetMediaKey(),
Length: int(msg.GetFileLength()),
Type: whatsmeow.GetMediaType(msg),
SHA256: msg.GetFileSha256(),
EncSHA256: msg.GetFileEncSha256(),
SHA256: msg.GetFileSHA256(),
EncSHA256: msg.GetFileEncSHA256(),
}, errorText)
} else if errors.Is(err, whatsmeow.ErrNoURLPresent) {
zerolog.Ctx(ctx).Debug().Msg("No URL present error for media message, ignoring...")
@ -3840,7 +3841,7 @@ func (portal *Portal) handleMediaRetry(retry *events.MediaRetry, source *User) {
portal.sendMediaRetryFailureEdit(ctx, intent, msg, err)
return
} else if retryData.GetResult() != waProto.MediaRetryNotification_SUCCESS {
errorName := waProto.MediaRetryNotification_ResultType_name[int32(retryData.GetResult())]
errorName := waMmsRetry.MediaRetryNotification_ResultType_name[int32(retryData.GetResult())]
if retryData.GetDirectPath() == "" {
log.Warn().Str("error_name", errorName).Msg("Got error response in media retry notification")
log.Debug().Any("error_content", retryData).Msg("Full error response content")
@ -4421,7 +4422,7 @@ func (portal *Portal) convertMatrixPollStart(ctx context.Context, sender *User,
}
ctxInfo := portal.generateContextInfo(ctx, content.RelatesTo)
var question string
question, ctxInfo.MentionedJid = portal.msc1767ToWhatsApp(content.PollStart.Question, true)
question, ctxInfo.MentionedJID = portal.msc1767ToWhatsApp(content.PollStart.Question, true)
if len(question) == 0 {
return nil, sender, nil, errPollMissingQuestion
}
@ -4465,7 +4466,7 @@ func (portal *Portal) generateContextInfo(ctx context.Context, relatesTo *event.
Msg("Failed to get reply target from database")
}
if replyToMsg != nil && !replyToMsg.IsFakeJID() && (replyToMsg.Type == database.MsgNormal || replyToMsg.Type == database.MsgMatrixPoll || replyToMsg.Type == database.MsgBeeperGallery) {
ctxInfo.StanzaId = &replyToMsg.JID
ctxInfo.StanzaID = &replyToMsg.JID
ctxInfo.Participant = proto.String(replyToMsg.Sender.ToNonAD().String())
// Using blank content here seems to work fine on all official WhatsApp apps.
//
@ -4577,7 +4578,7 @@ func (portal *Portal) convertMatrixMessage(ctx context.Context, sender *User, ev
return nil, sender, extraMeta, errMNoticeDisabled
}
if content.Format == event.FormatHTML {
text, ctxInfo.MentionedJid = portal.bridge.Formatter.ParseMatrix(content.FormattedBody, content.Mentions)
text, ctxInfo.MentionedJID = portal.bridge.Formatter.ParseMatrix(content.FormattedBody, content.Mentions)
}
if content.MsgType == event.MsgEmote && !relaybotFormatted {
text = "/me " + text
@ -4590,7 +4591,7 @@ func (portal *Portal) convertMatrixMessage(ctx context.Context, sender *User, ev
if ctx.Err() != nil {
return nil, sender, extraMeta, ctx.Err()
}
if ctxInfo.StanzaId == nil && ctxInfo.MentionedJid == nil && ctxInfo.Expiration == nil && !hasPreview {
if ctxInfo.StanzaID == nil && ctxInfo.MentionedJID == nil && ctxInfo.Expiration == nil && !hasPreview {
// No need for extended message
msg.ExtendedTextMessage = nil
msg.Conversation = &text
@ -4601,17 +4602,17 @@ func (portal *Portal) convertMatrixMessage(ctx context.Context, sender *User, ev
return nil, sender, extraMeta, err
}
extraMeta.MediaHandle = media.Handle
ctxInfo.MentionedJid = media.MentionedJIDs
ctxInfo.MentionedJID = media.MentionedJIDs
msg.ImageMessage = &waProto.ImageMessage{
ContextInfo: ctxInfo,
Caption: &media.Caption,
JpegThumbnail: media.Thumbnail,
Url: &media.URL,
JPEGThumbnail: media.Thumbnail,
URL: &media.URL,
DirectPath: &media.DirectPath,
MediaKey: media.MediaKey,
Mimetype: &content.GetInfo().MimeType,
FileEncSha256: media.FileEncSHA256,
FileSha256: media.FileSHA256,
FileEncSHA256: media.FileEncSHA256,
FileSHA256: media.FileSHA256,
FileLength: proto.Uint64(uint64(media.FileLength)),
}
case event.MsgBeeperGallery:
@ -4631,13 +4632,13 @@ func (portal *Portal) convertMatrixMessage(ctx context.Context, sender *User, ev
}
imageMsg := &waProto.ImageMessage{
ContextInfo: ctxInfo,
JpegThumbnail: media.Thumbnail,
Url: &media.URL,
JPEGThumbnail: media.Thumbnail,
URL: &media.URL,
DirectPath: &media.DirectPath,
MediaKey: media.MediaKey,
Mimetype: &part.GetInfo().MimeType,
FileEncSha256: media.FileEncSHA256,
FileSha256: media.FileSHA256,
FileEncSHA256: media.FileEncSHA256,
FileSHA256: media.FileSHA256,
FileLength: proto.Uint64(uint64(media.FileLength)),
}
if i == 0 {
@ -4654,16 +4655,16 @@ func (portal *Portal) convertMatrixMessage(ctx context.Context, sender *User, ev
return nil, sender, extraMeta, err
}
extraMeta.MediaHandle = media.Handle
ctxInfo.MentionedJid = media.MentionedJIDs
ctxInfo.MentionedJID = media.MentionedJIDs
msg.StickerMessage = &waProto.StickerMessage{
ContextInfo: ctxInfo,
PngThumbnail: media.Thumbnail,
Url: &media.URL,
URL: &media.URL,
DirectPath: &media.DirectPath,
MediaKey: media.MediaKey,
Mimetype: &content.GetInfo().MimeType,
FileEncSha256: media.FileEncSHA256,
FileSha256: media.FileSHA256,
FileEncSHA256: media.FileEncSHA256,
FileSHA256: media.FileSHA256,
FileLength: proto.Uint64(uint64(media.FileLength)),
}
case event.MsgVideo:
@ -4674,19 +4675,19 @@ func (portal *Portal) convertMatrixMessage(ctx context.Context, sender *User, ev
}
duration := uint32(content.GetInfo().Duration / 1000)
extraMeta.MediaHandle = media.Handle
ctxInfo.MentionedJid = media.MentionedJIDs
ctxInfo.MentionedJID = media.MentionedJIDs
msg.VideoMessage = &waProto.VideoMessage{
ContextInfo: ctxInfo,
Caption: &media.Caption,
JpegThumbnail: media.Thumbnail,
Url: &media.URL,
JPEGThumbnail: media.Thumbnail,
URL: &media.URL,
DirectPath: &media.DirectPath,
MediaKey: media.MediaKey,
Mimetype: &content.GetInfo().MimeType,
GifPlayback: &gifPlayback,
Seconds: &duration,
FileEncSha256: media.FileEncSHA256,
FileSha256: media.FileSHA256,
FileEncSHA256: media.FileEncSHA256,
FileSHA256: media.FileSHA256,
FileLength: proto.Uint64(uint64(media.FileLength)),
}
case event.MsgAudio:
@ -4698,19 +4699,19 @@ func (portal *Portal) convertMatrixMessage(ctx context.Context, sender *User, ev
duration := uint32(content.GetInfo().Duration / 1000)
msg.AudioMessage = &waProto.AudioMessage{
ContextInfo: ctxInfo,
Url: &media.URL,
URL: &media.URL,
DirectPath: &media.DirectPath,
MediaKey: media.MediaKey,
Mimetype: &content.GetInfo().MimeType,
Seconds: &duration,
FileEncSha256: media.FileEncSHA256,
FileSha256: media.FileSHA256,
FileEncSHA256: media.FileEncSHA256,
FileSHA256: media.FileSHA256,
FileLength: proto.Uint64(uint64(media.FileLength)),
}
_, isMSC3245Voice := evt.Content.Raw["org.matrix.msc3245.voice"]
if isMSC3245Voice {
msg.AudioMessage.Waveform = getUnstableWaveform(evt.Content.Raw)
msg.AudioMessage.Ptt = proto.Bool(true)
msg.AudioMessage.PTT = proto.Bool(true)
// hacky hack to add the codecs param that whatsapp seems to require
msg.AudioMessage.Mimetype = proto.String(addCodecToMime(content.GetInfo().MimeType, "opus"))
}
@ -4723,15 +4724,15 @@ func (portal *Portal) convertMatrixMessage(ctx context.Context, sender *User, ev
msg.DocumentMessage = &waProto.DocumentMessage{
ContextInfo: ctxInfo,
Caption: &media.Caption,
JpegThumbnail: media.Thumbnail,
Url: &media.URL,
JPEGThumbnail: media.Thumbnail,
URL: &media.URL,
DirectPath: &media.DirectPath,
Title: &media.FileName,
FileName: &media.FileName,
MediaKey: media.MediaKey,
Mimetype: &content.GetInfo().MimeType,
FileEncSha256: media.FileEncSHA256,
FileSha256: media.FileSHA256,
FileEncSHA256: media.FileEncSHA256,
FileSHA256: media.FileSHA256,
FileLength: proto.Uint64(uint64(media.FileLength)),
}
if media.Caption != "" {
@ -4764,12 +4765,12 @@ func (portal *Portal) convertMatrixMessage(ctx context.Context, sender *User, ev
ProtocolMessage: &waProto.ProtocolMessage{
Key: &waProto.MessageKey{
FromMe: proto.Bool(true),
Id: proto.String(editRootMsg.JID),
RemoteJid: proto.String(portal.Key.JID.String()),
ID: proto.String(editRootMsg.JID),
RemoteJID: proto.String(portal.Key.JID.String()),
},
Type: waProto.ProtocolMessage_MESSAGE_EDIT.Enum(),
EditedMessage: msg,
TimestampMs: proto.Int64(evt.Timestamp),
TimestampMS: proto.Int64(evt.Timestamp),
},
},
},
@ -5008,13 +5009,13 @@ func (portal *Portal) sendReactionToWhatsApp(sender *User, id types.MessageID, t
return sender.Client.SendMessage(ctx, portal.Key.JID, &waProto.Message{
ReactionMessage: &waProto.ReactionMessage{
Key: &waProto.MessageKey{
RemoteJid: proto.String(portal.Key.JID.String()),
RemoteJID: proto.String(portal.Key.JID.String()),
FromMe: proto.Bool(target.Sender.User == sender.JID.User),
Id: proto.String(target.JID),
ID: proto.String(target.JID),
Participant: messageKeyParticipant,
},
Text: proto.String(key),
SenderTimestampMs: proto.Int64(timestamp),
SenderTimestampMS: proto.Int64(timestamp),
},
}, whatsmeow.SendRequestExtra{ID: id})
}
@ -5100,8 +5101,8 @@ func (portal *Portal) HandleMatrixRedaction(ctx context.Context, sender *User, e
} else {
key := &waProto.MessageKey{
FromMe: proto.Bool(true),
Id: proto.String(msg.JID),
RemoteJid: proto.String(portal.Key.JID.String()),
ID: proto.String(msg.JID),
RemoteJID: proto.String(portal.Key.JID.String()),
}
if msg.Sender.User != sender.JID.User {
if portal.IsPrivateChat() {

View file

@ -46,7 +46,7 @@ func (portal *Portal) convertURLPreviewToBeeper(ctx context.Context, intent *app
output := &event.BeeperLinkPreview{
MatchedURL: msg.GetMatchedText(),
LinkPreview: event.LinkPreview{
CanonicalURL: msg.GetCanonicalUrl(),
CanonicalURL: msg.GetCanonicalURL(),
Title: msg.GetTitle(),
Description: msg.GetDescription(),
},
@ -63,8 +63,8 @@ func (portal *Portal) convertURLPreviewToBeeper(ctx context.Context, intent *app
zerolog.Ctx(ctx).Err(err).Msg("Failed to download thumbnail for link preview")
}
}
if thumbnailData == nil && msg.JpegThumbnail != nil {
thumbnailData = msg.JpegThumbnail
if thumbnailData == nil && msg.JPEGThumbnail != nil {
thumbnailData = msg.JPEGThumbnail
}
if thumbnailData != nil {
output.ImageHeight = int(msg.GetThumbnailHeight())
@ -140,7 +140,7 @@ func (portal *Portal) convertURLPreviewToWhatsApp(ctx context.Context, sender *U
dest.MatchedText = &preview.MatchedURL
if len(preview.CanonicalURL) > 0 {
dest.CanonicalUrl = &preview.CanonicalURL
dest.CanonicalURL = &preview.CanonicalURL
}
if len(preview.Description) > 0 {
dest.Description = &preview.Description
@ -174,12 +174,12 @@ func (portal *Portal) convertURLPreviewToWhatsApp(ctx context.Context, sender *U
log.Err(err).Msg("Failed to reupload URL preview thumbnail")
return true
}
dest.ThumbnailSha256 = uploadResp.FileSHA256
dest.ThumbnailEncSha256 = uploadResp.FileEncSHA256
dest.ThumbnailSHA256 = uploadResp.FileSHA256
dest.ThumbnailEncSHA256 = uploadResp.FileEncSHA256
dest.ThumbnailDirectPath = &uploadResp.DirectPath
dest.MediaKey = uploadResp.MediaKey
var width, height int
dest.JpegThumbnail, width, height, err = createThumbnailAndGetSize(data, false)
dest.JPEGThumbnail, width, height, err = createThumbnailAndGetSize(data, false)
if err != nil {
log.Err(err).Msg("Failed to create JPEG thumbnail for URL preview")
}

View file

@ -765,7 +765,7 @@ func (user *User) sendHackyPhonePing(ctx context.Context) {
lastKeyID, err := user.GetLastAppStateKeyID(ctx)
if lastKeyID != nil {
keyIDs = append(keyIDs, &waProto.AppStateSyncKeyId{
KeyId: lastKeyID,
KeyID: lastKeyID,
})
} else {
user.zlog.Warn().Err(err).Msg("Failed to get last app state key ID to send hacky phone ping - sending empty request")
@ -774,7 +774,7 @@ func (user *User) sendHackyPhonePing(ctx context.Context) {
ProtocolMessage: &waProto.ProtocolMessage{
Type: waProto.ProtocolMessage_APP_STATE_SYNC_KEY_REQUEST.Enum(),
AppStateSyncKeyRequest: &waProto.AppStateSyncKeyRequest{
KeyIds: keyIDs,
KeyIDs: keyIDs,
},
},
}, whatsmeow.SendRequestExtra{Peer: true, ID: msgID})