forked from MirrorHub/mautrix-whatsapp
Implement matrix->whatsapp formatting and fix whatsapp->matrix files
This commit is contained in:
parent
d13bf4ae64
commit
b62a85a6df
2 changed files with 116 additions and 16 deletions
112
portal.go
112
portal.go
|
@ -28,6 +28,10 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"net/http"
|
"net/http"
|
||||||
"maunium.net/go/mautrix-whatsapp/whatsapp-ext"
|
"maunium.net/go/mautrix-whatsapp/whatsapp-ext"
|
||||||
|
"mime"
|
||||||
|
"image"
|
||||||
|
"bytes"
|
||||||
|
"maunium.net/go/gomatrix/format"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (user *User) GetPortalByMXID(mxid types.MatrixRoomID) *Portal {
|
func (user *User) GetPortalByMXID(mxid types.MatrixRoomID) *Portal {
|
||||||
|
@ -130,8 +134,8 @@ func (portal *Portal) UpdateAvatar() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
mime := http.DetectContentType(data)
|
mimeType := http.DetectContentType(data)
|
||||||
resp, err := portal.MainIntent().UploadBytes(data, mime)
|
resp, err := portal.MainIntent().UploadBytes(data, mimeType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
portal.log.Errorln("Failed to upload avatar:", err)
|
portal.log.Errorln("Failed to upload avatar:", err)
|
||||||
return false
|
return false
|
||||||
|
@ -278,6 +282,18 @@ func (portal *Portal) GetMessageIntent(info whatsapp.MessageInfo) *appservice.In
|
||||||
return puppet.Intent()
|
return puppet.Intent()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (portal *Portal) GetRelations(info whatsapp.MessageInfo) (reply gomatrix.RelatesTo) {
|
||||||
|
if len(info.QuotedMessageID) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
message := portal.bridge.DB.Message.GetByJID(portal.Owner, info.QuotedMessageID)
|
||||||
|
if message != nil {
|
||||||
|
reply.InReplyTo.EventID = message.MXID
|
||||||
|
}
|
||||||
|
return
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func (portal *Portal) HandleTextMessage(message whatsapp.TextMessage) {
|
func (portal *Portal) HandleTextMessage(message whatsapp.TextMessage) {
|
||||||
if portal.IsDuplicate(message.Info.Id) {
|
if portal.IsDuplicate(message.Info.Id) {
|
||||||
return
|
return
|
||||||
|
@ -290,7 +306,11 @@ func (portal *Portal) HandleTextMessage(message whatsapp.TextMessage) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := intent.SendText(portal.MXID, message.Text)
|
resp, err := intent.SendMassagedMessageEvent(portal.MXID, gomatrix.EventMessage, gomatrix.Content{
|
||||||
|
Body: message.Text,
|
||||||
|
MsgType: gomatrix.MsgText,
|
||||||
|
RelatesTo: portal.GetRelations(message.Info),
|
||||||
|
}, int64(message.Info.Timestamp*1000))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
portal.log.Errorfln("Failed to handle message %s: %v", message.Info.Id, err)
|
portal.log.Errorfln("Failed to handle message %s: %v", message.Info.Id, err)
|
||||||
return
|
return
|
||||||
|
@ -299,7 +319,7 @@ func (portal *Portal) HandleTextMessage(message whatsapp.TextMessage) {
|
||||||
portal.log.Debugln("Handled message", message.Info.Id, "->", resp.EventID)
|
portal.log.Debugln("Handled message", message.Info.Id, "->", resp.EventID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (portal *Portal) HandleMediaMessage(download func() ([]byte, error), info whatsapp.MessageInfo, mime, caption string) {
|
func (portal *Portal) HandleMediaMessage(download func() ([]byte, error), thumbnail []byte, info whatsapp.MessageInfo, mimeType, caption string) {
|
||||||
if portal.IsDuplicate(info.Id) {
|
if portal.IsDuplicate(info.Id) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -311,17 +331,65 @@ func (portal *Portal) HandleMediaMessage(download func() ([]byte, error), info w
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
img, err := download()
|
data, err := download()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
portal.log.Errorln("Failed to download media:", err)
|
portal.log.Errorln("Failed to download media:", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
uploaded, err := intent.UploadBytes(img, mime)
|
|
||||||
|
uploaded, err := intent.UploadBytes(data, mimeType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
portal.log.Errorln("Failed to upload media:", err)
|
portal.log.Errorln("Failed to upload media:", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
resp, err := intent.SendImage(portal.MXID, caption, uploaded.ContentURI)
|
if len(caption) == 0 {
|
||||||
|
caption = info.Id
|
||||||
|
exts, _ := mime.ExtensionsByType(mimeType)
|
||||||
|
if exts != nil && len(exts) > 0 {
|
||||||
|
caption += exts[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
content := gomatrix.Content{
|
||||||
|
Body: caption,
|
||||||
|
URL: uploaded.ContentURI,
|
||||||
|
Info: gomatrix.FileInfo{
|
||||||
|
Size: len(data),
|
||||||
|
MimeType: mimeType,
|
||||||
|
},
|
||||||
|
RelatesTo: portal.GetRelations(info),
|
||||||
|
}
|
||||||
|
|
||||||
|
if thumbnail != nil {
|
||||||
|
thumbnailMime := http.DetectContentType(thumbnail)
|
||||||
|
uploadedThumbnail, _ := intent.UploadBytes(thumbnail, thumbnailMime)
|
||||||
|
if uploadedThumbnail != nil {
|
||||||
|
content.Info.ThumbnailURL = uploadedThumbnail.ContentURI
|
||||||
|
cfg, _, _ := image.DecodeConfig(bytes.NewReader(data))
|
||||||
|
content.Info.ThumbnailInfo = &gomatrix.FileInfo{
|
||||||
|
Size: len(thumbnail),
|
||||||
|
Width: cfg.Width,
|
||||||
|
Height: cfg.Height,
|
||||||
|
MimeType: thumbnailMime,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch strings.ToLower(strings.Split(mimeType, "/")[0]) {
|
||||||
|
case "image":
|
||||||
|
content.MsgType = gomatrix.MsgImage
|
||||||
|
cfg, _, _ := image.DecodeConfig(bytes.NewReader(data))
|
||||||
|
content.Info.Width = cfg.Width
|
||||||
|
content.Info.Height = cfg.Height
|
||||||
|
case "video":
|
||||||
|
content.MsgType = gomatrix.MsgVideo
|
||||||
|
case "audio":
|
||||||
|
content.MsgType = gomatrix.MsgAudio
|
||||||
|
default:
|
||||||
|
content.MsgType = gomatrix.MsgFile
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := intent.SendMassagedMessageEvent(portal.MXID, gomatrix.EventMessage, content, int64(info.Timestamp*1000))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
portal.log.Errorfln("Failed to handle message %s: %v", info.Id, err)
|
portal.log.Errorfln("Failed to handle message %s: %v", info.Id, err)
|
||||||
return
|
return
|
||||||
|
@ -330,12 +398,40 @@ func (portal *Portal) HandleMediaMessage(download func() ([]byte, error), info w
|
||||||
portal.log.Debugln("Handled message", info.Id, "->", resp.EventID)
|
portal.log.Debugln("Handled message", info.Id, "->", resp.EventID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var htmlParser = format.HTMLParser{
|
||||||
|
TabsToSpaces: 4,
|
||||||
|
Newline: "\n",
|
||||||
|
|
||||||
|
PillConverter: func(mxid, eventID string) string {
|
||||||
|
return mxid
|
||||||
|
},
|
||||||
|
BoldConverter: func(text string) string {
|
||||||
|
return fmt.Sprintf("*%s*", text)
|
||||||
|
},
|
||||||
|
ItalicConverter: func(text string) string {
|
||||||
|
return fmt.Sprintf("_%s_", text)
|
||||||
|
},
|
||||||
|
StrikethroughConverter: func(text string) string {
|
||||||
|
return fmt.Sprintf("~%s~", text)
|
||||||
|
},
|
||||||
|
MonospaceConverter: func(text string) string {
|
||||||
|
return fmt.Sprintf("```%s```", text)
|
||||||
|
},
|
||||||
|
MonospaceBlockConverter: func(text string) string {
|
||||||
|
return fmt.Sprintf("```%s```", text)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
func (portal *Portal) HandleMatrixMessage(evt *gomatrix.Event) {
|
func (portal *Portal) HandleMatrixMessage(evt *gomatrix.Event) {
|
||||||
var err error
|
var err error
|
||||||
switch evt.Content.MsgType {
|
switch evt.Content.MsgType {
|
||||||
case gomatrix.MsgText:
|
case gomatrix.MsgText:
|
||||||
|
text := evt.Content.Body
|
||||||
|
if evt.Content.Format == gomatrix.FormatHTML {
|
||||||
|
text = htmlParser.Parse(evt.Content.FormattedBody)
|
||||||
|
}
|
||||||
err = portal.user.Conn.Send(whatsapp.TextMessage{
|
err = portal.user.Conn.Send(whatsapp.TextMessage{
|
||||||
Text: evt.Content.Body,
|
Text: text,
|
||||||
Info: whatsapp.MessageInfo{
|
Info: whatsapp.MessageInfo{
|
||||||
RemoteJid: portal.JID,
|
RemoteJid: portal.JID,
|
||||||
},
|
},
|
||||||
|
|
20
user.go
20
user.go
|
@ -24,7 +24,6 @@ import (
|
||||||
log "maunium.net/go/maulogger"
|
log "maunium.net/go/maulogger"
|
||||||
"maunium.net/go/mautrix-whatsapp/types"
|
"maunium.net/go/mautrix-whatsapp/types"
|
||||||
"strings"
|
"strings"
|
||||||
"encoding/json"
|
|
||||||
"sync"
|
"sync"
|
||||||
"maunium.net/go/mautrix-whatsapp/whatsapp-ext"
|
"maunium.net/go/mautrix-whatsapp/whatsapp-ext"
|
||||||
)
|
)
|
||||||
|
@ -186,10 +185,7 @@ func (user *User) Login(roomID types.MatrixRoomID) {
|
||||||
func (user *User) Sync() {
|
func (user *User) Sync() {
|
||||||
user.log.Debugln("Syncing...")
|
user.log.Debugln("Syncing...")
|
||||||
user.Conn.Contacts()
|
user.Conn.Contacts()
|
||||||
user.log.Debugln(user.Conn.Store.Contacts)
|
|
||||||
for jid, contact := range user.Conn.Store.Contacts {
|
for jid, contact := range user.Conn.Store.Contacts {
|
||||||
dat, _ := json.Marshal(&contact)
|
|
||||||
user.log.Debugln(string(dat))
|
|
||||||
if strings.HasSuffix(jid, puppetJIDStrippedSuffix) {
|
if strings.HasSuffix(jid, puppetJIDStrippedSuffix) {
|
||||||
puppet := user.GetPuppetByJID(contact.Jid)
|
puppet := user.GetPuppetByJID(contact.Jid)
|
||||||
puppet.Sync(contact)
|
puppet.Sync(contact)
|
||||||
|
@ -216,15 +212,23 @@ func (user *User) HandleTextMessage(message whatsapp.TextMessage) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (user *User) HandleImageMessage(message whatsapp.ImageMessage) {
|
func (user *User) HandleImageMessage(message whatsapp.ImageMessage) {
|
||||||
// user.log.Debugln("Received image message:", message)
|
|
||||||
portal := user.GetPortalByJID(message.Info.RemoteJid)
|
portal := user.GetPortalByJID(message.Info.RemoteJid)
|
||||||
portal.HandleMediaMessage(message.Download, message.Info, message.Type, message.Caption)
|
portal.HandleMediaMessage(message.Download, message.Thumbnail, message.Info, message.Type, message.Caption)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (user *User) HandleVideoMessage(message whatsapp.VideoMessage) {
|
func (user *User) HandleVideoMessage(message whatsapp.VideoMessage) {
|
||||||
// user.log.Debugln("Received video message:", message)
|
|
||||||
portal := user.GetPortalByJID(message.Info.RemoteJid)
|
portal := user.GetPortalByJID(message.Info.RemoteJid)
|
||||||
portal.HandleMediaMessage(message.Download, message.Info, message.Type, message.Caption)
|
portal.HandleMediaMessage(message.Download, message.Thumbnail, message.Info, message.Type, message.Caption)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (user *User) HandleAudioMessage(message whatsapp.AudioMessage) {
|
||||||
|
portal := user.GetPortalByJID(message.Info.RemoteJid)
|
||||||
|
portal.HandleMediaMessage(message.Download, nil, message.Info, message.Type, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (user *User) HandleDocumentMessage(message whatsapp.DocumentMessage) {
|
||||||
|
portal := user.GetPortalByJID(message.Info.RemoteJid)
|
||||||
|
portal.HandleMediaMessage(message.Download, message.Thumbnail, message.Info, message.Type, message.Title)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (user *User) HandleJsonMessage(message string) {
|
func (user *User) HandleJsonMessage(message string) {
|
||||||
|
|
Loading…
Reference in a new issue