mirror of
https://github.com/tulir/mautrix-whatsapp
synced 2024-11-13 05:21:51 +01:00
Update whatsmeow for WhatsApp web version 2.3000.x
This commit is contained in:
parent
00a9b0b783
commit
73266af075
7 changed files with 102 additions and 122 deletions
10
go.mod
10
go.mod
|
@ -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
20
go.sum
|
@ -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=
|
||||
|
|
|
@ -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
47
main.go
|
@ -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
127
portal.go
|
@ -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() {
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
4
user.go
4
user.go
|
@ -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})
|
||||
|
|
Loading…
Reference in a new issue