forked from MirrorHub/mautrix-whatsapp
Add bridging of location messages to Matrix
This commit is contained in:
parent
e4a160e650
commit
210b1caf65
3 changed files with 87 additions and 32 deletions
|
@ -25,7 +25,8 @@
|
||||||
* [x] Plain text
|
* [x] Plain text
|
||||||
* [x] Formatted messages
|
* [x] Formatted messages
|
||||||
* [x] Media/files
|
* [x] Media/files
|
||||||
* [ ] Location messages
|
* [x] Location messages
|
||||||
|
* [x] Contact messages
|
||||||
* [x] Replies
|
* [x] Replies
|
||||||
* [ ] Chat types
|
* [ ] Chat types
|
||||||
* [x] Private chat
|
* [x] Private chat
|
||||||
|
|
112
portal.go
112
portal.go
|
@ -26,6 +26,7 @@ import (
|
||||||
"image/gif"
|
"image/gif"
|
||||||
"image/jpeg"
|
"image/jpeg"
|
||||||
"image/png"
|
"image/png"
|
||||||
|
"math"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"mime"
|
"mime"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -207,6 +208,8 @@ func (portal *Portal) handleMessage(msg PortalMessage) {
|
||||||
portal.HandleMediaMessage(msg.source, data.Download, data.Thumbnail, data.Info, data.ContextInfo, data.Type, data.Title, false)
|
portal.HandleMediaMessage(msg.source, data.Download, data.Thumbnail, data.Info, data.ContextInfo, data.Type, data.Title, false)
|
||||||
case whatsapp.ContactMessage:
|
case whatsapp.ContactMessage:
|
||||||
portal.HandleContactMessage(msg.source, data)
|
portal.HandleContactMessage(msg.source, data)
|
||||||
|
case whatsapp.LocationMessage:
|
||||||
|
portal.HandleLocationMessage(msg.source, data)
|
||||||
case whatsappExt.MessageRevocation:
|
case whatsappExt.MessageRevocation:
|
||||||
portal.HandleMessageRevoke(msg.source, data)
|
portal.HandleMessageRevoke(msg.source, data)
|
||||||
case FakeMessage:
|
case FakeMessage:
|
||||||
|
@ -264,7 +267,22 @@ func (portal *Portal) markHandled(source *User, message *waProto.WebMessageInfo,
|
||||||
portal.recentlyHandled[index] = msg.JID
|
portal.recentlyHandled[index] = msg.JID
|
||||||
}
|
}
|
||||||
|
|
||||||
func (portal *Portal) startHandling(info whatsapp.MessageInfo) bool {
|
func (portal *Portal) getMessageIntent(user *User, info whatsapp.MessageInfo) *appservice.IntentAPI {
|
||||||
|
if info.FromMe {
|
||||||
|
return portal.bridge.GetPuppetByJID(user.JID).IntentFor(portal)
|
||||||
|
} else if portal.IsPrivateChat() {
|
||||||
|
return portal.MainIntent()
|
||||||
|
} else if len(info.SenderJid) == 0 {
|
||||||
|
if len(info.Source.GetParticipant()) != 0 {
|
||||||
|
info.SenderJid = info.Source.GetParticipant()
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return portal.bridge.GetPuppetByJID(info.SenderJid).IntentFor(portal)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (portal *Portal) startHandling(source *User, info whatsapp.MessageInfo) *appservice.IntentAPI {
|
||||||
// TODO these should all be trace logs
|
// TODO these should all be trace logs
|
||||||
if portal.lastMessageTs > info.Timestamp+1 {
|
if portal.lastMessageTs > info.Timestamp+1 {
|
||||||
portal.log.Debugfln("Not handling %s: message is older (%d) than last bridge message (%d)", info.Id, info.Timestamp, portal.lastMessageTs)
|
portal.log.Debugfln("Not handling %s: message is older (%d) than last bridge message (%d)", info.Id, info.Timestamp, portal.lastMessageTs)
|
||||||
|
@ -275,9 +293,9 @@ func (portal *Portal) startHandling(info whatsapp.MessageInfo) bool {
|
||||||
} else {
|
} else {
|
||||||
portal.log.Debugfln("Starting handling of %s (ts: %d)", info.Id, info.Timestamp)
|
portal.log.Debugfln("Starting handling of %s (ts: %d)", info.Id, info.Timestamp)
|
||||||
portal.lastMessageTs = info.Timestamp
|
portal.lastMessageTs = info.Timestamp
|
||||||
return true
|
return portal.getMessageIntent(source, info)
|
||||||
}
|
}
|
||||||
return false
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (portal *Portal) finishHandling(source *User, message *waProto.WebMessageInfo, mxid id.EventID) {
|
func (portal *Portal) finishHandling(source *User, message *waProto.WebMessageInfo, mxid id.EventID) {
|
||||||
|
@ -954,21 +972,6 @@ func (portal *Portal) MainIntent() *appservice.IntentAPI {
|
||||||
return portal.bridge.Bot
|
return portal.bridge.Bot
|
||||||
}
|
}
|
||||||
|
|
||||||
func (portal *Portal) GetMessageIntent(user *User, info whatsapp.MessageInfo) *appservice.IntentAPI {
|
|
||||||
if info.FromMe {
|
|
||||||
return portal.bridge.GetPuppetByJID(user.JID).IntentFor(portal)
|
|
||||||
} else if portal.IsPrivateChat() {
|
|
||||||
return portal.MainIntent()
|
|
||||||
} else if len(info.SenderJid) == 0 {
|
|
||||||
if len(info.Source.GetParticipant()) != 0 {
|
|
||||||
info.SenderJid = info.Source.GetParticipant()
|
|
||||||
} else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return portal.bridge.GetPuppetByJID(info.SenderJid).IntentFor(portal)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (portal *Portal) SetReply(content *event.MessageEventContent, info whatsapp.ContextInfo) {
|
func (portal *Portal) SetReply(content *event.MessageEventContent, info whatsapp.ContextInfo) {
|
||||||
if len(info.QuotedMessageID) == 0 {
|
if len(info.QuotedMessageID) == 0 {
|
||||||
return
|
return
|
||||||
|
@ -1063,11 +1066,7 @@ func (portal *Portal) sendMessage(intent *appservice.IntentAPI, eventType event.
|
||||||
}
|
}
|
||||||
|
|
||||||
func (portal *Portal) HandleTextMessage(source *User, message whatsapp.TextMessage) {
|
func (portal *Portal) HandleTextMessage(source *User, message whatsapp.TextMessage) {
|
||||||
if !portal.startHandling(message.Info) {
|
intent := portal.startHandling(source, message.Info)
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
intent := portal.GetMessageIntent(source, message.Info)
|
|
||||||
if intent == nil {
|
if intent == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1089,12 +1088,67 @@ func (portal *Portal) HandleTextMessage(source *User, message whatsapp.TextMessa
|
||||||
portal.finishHandling(source, message.Info.Source, resp.EventID)
|
portal.finishHandling(source, message.Info.Source, resp.EventID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (portal *Portal) HandleContactMessage(source *User, message whatsapp.ContactMessage) {
|
func (portal *Portal) HandleLocationMessage(source *User, message whatsapp.LocationMessage) {
|
||||||
if !portal.startHandling(message.Info) {
|
intent := portal.startHandling(source, message.Info)
|
||||||
|
if intent == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
intent := portal.GetMessageIntent(source, message.Info)
|
url := message.Url
|
||||||
|
if len(url) == 0 {
|
||||||
|
url = fmt.Sprintf("https://maps.google.com/?q=%.5f,%.5f", message.DegreesLatitude, message.DegreesLongitude)
|
||||||
|
}
|
||||||
|
name := message.Name
|
||||||
|
if len(name) == 0 {
|
||||||
|
latChar := 'N'
|
||||||
|
if message.DegreesLatitude < 0 {
|
||||||
|
latChar = 'S'
|
||||||
|
}
|
||||||
|
longChar := 'E'
|
||||||
|
if message.DegreesLongitude < 0 {
|
||||||
|
longChar = 'W'
|
||||||
|
}
|
||||||
|
name = fmt.Sprintf("%.4f° %c %.4f° %c", math.Abs(message.DegreesLatitude), latChar, math.Abs(message.DegreesLongitude), longChar)
|
||||||
|
}
|
||||||
|
|
||||||
|
content := &event.MessageEventContent{
|
||||||
|
MsgType: event.MsgLocation,
|
||||||
|
Body: fmt.Sprintf("Location: %s\n%s\n%s", name, message.Address, url),
|
||||||
|
Format: event.FormatHTML,
|
||||||
|
FormattedBody: fmt.Sprintf("Location: <a href='%s'>%s</a><br>%s", url, name, message.Address),
|
||||||
|
GeoURI: fmt.Sprintf("geo:%.5f,%.5f", message.DegreesLatitude, message.DegreesLongitude),
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(message.JpegThumbnail) > 0 {
|
||||||
|
thumbnailMime := http.DetectContentType(message.JpegThumbnail)
|
||||||
|
uploadedThumbnail, _ := intent.UploadBytes(message.JpegThumbnail, thumbnailMime)
|
||||||
|
if uploadedThumbnail != nil {
|
||||||
|
cfg, _, _ := image.DecodeConfig(bytes.NewReader(message.JpegThumbnail))
|
||||||
|
content.Info = &event.FileInfo{
|
||||||
|
ThumbnailInfo: &event.FileInfo{
|
||||||
|
Size: len(message.JpegThumbnail),
|
||||||
|
Width: cfg.Width,
|
||||||
|
Height: cfg.Height,
|
||||||
|
MimeType: thumbnailMime,
|
||||||
|
},
|
||||||
|
ThumbnailURL: uploadedThumbnail.ContentURI.CUString(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
portal.SetReply(content, message.ContextInfo)
|
||||||
|
|
||||||
|
_, _ = intent.UserTyping(portal.MXID, false, 0)
|
||||||
|
resp, err := portal.sendMessage(intent, event.EventMessage, content, int64(message.Info.Timestamp*1000))
|
||||||
|
if err != nil {
|
||||||
|
portal.log.Errorfln("Failed to handle message %s: %v", message.Info.Id, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
portal.finishHandling(source, message.Info.Source, resp.EventID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (portal *Portal) HandleContactMessage(source *User, message whatsapp.ContactMessage) {
|
||||||
|
intent := portal.startHandling(source, message.Info)
|
||||||
if intent == nil {
|
if intent == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1142,11 +1196,7 @@ func (portal *Portal) sendMediaBridgeFailure(source *User, intent *appservice.In
|
||||||
}
|
}
|
||||||
|
|
||||||
func (portal *Portal) HandleMediaMessage(source *User, download func() ([]byte, error), thumbnail []byte, info whatsapp.MessageInfo, context whatsapp.ContextInfo, mimeType, caption string, sendAsSticker bool) {
|
func (portal *Portal) HandleMediaMessage(source *User, download func() ([]byte, error), thumbnail []byte, info whatsapp.MessageInfo, context whatsapp.ContextInfo, mimeType, caption string, sendAsSticker bool) {
|
||||||
if !portal.startHandling(info) {
|
intent := portal.startHandling(source, info)
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
intent := portal.GetMessageIntent(source, info)
|
|
||||||
if intent == nil {
|
if intent == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
4
user.go
4
user.go
|
@ -698,6 +698,10 @@ func (user *User) HandleContactMessage(message whatsapp.ContactMessage) {
|
||||||
user.putMessage(PortalMessage{message.Info.RemoteJid, user, message, message.Info.Timestamp})
|
user.putMessage(PortalMessage{message.Info.RemoteJid, user, message, message.Info.Timestamp})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (user *User) HandleLocationMessage(message whatsapp.LocationMessage) {
|
||||||
|
user.putMessage(PortalMessage{message.Info.RemoteJid, user, message, message.Info.Timestamp})
|
||||||
|
}
|
||||||
|
|
||||||
func (user *User) HandleMessageRevoke(message whatsappExt.MessageRevocation) {
|
func (user *User) HandleMessageRevoke(message whatsappExt.MessageRevocation) {
|
||||||
user.putMessage(PortalMessage{message.RemoteJid, user, message, 0})
|
user.putMessage(PortalMessage{message.RemoteJid, user, message, 0})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue