diff --git a/ROADMAP.md b/ROADMAP.md index 17314fe..d08bfda 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -20,9 +20,9 @@ * [ ] Topic * [ ] Initial room metadata * WhatsApp → Matrix - * [ ] Message content + * [x] Message content * [x] Plain text - * [ ] Formatted messages + * [x] Formatted messages * [x] Media/files * [ ] Message deletions * [x] Avatars diff --git a/portal.go b/portal.go index d37b21b..97c109d 100644 --- a/portal.go +++ b/portal.go @@ -20,10 +20,12 @@ import ( "bytes" "encoding/hex" "fmt" + "html" "image" "math/rand" "mime" "net/http" + "regexp" "strings" "sync" @@ -299,7 +301,26 @@ func (portal *Portal) SetReply(content *gomatrix.Content, info whatsapp.MessageI content.SetReply(event) } return +} +var codeBlockRegex = regexp.MustCompile("```((?:.|\n)+?)```") +var italicRegex = regexp.MustCompile("([\\s>~*]|^)_(.+?)_([^a-zA-Z\\d]|$)") +var boldRegex = regexp.MustCompile("([\\s>_~]|^)\\*(.+?)\\*([^a-zA-Z\\d]|$)") +var strikethroughRegex = regexp.MustCompile("([\\s>_*]|^)~(.+?)~([^a-zA-Z\\d]|$)") + +var whatsAppFormat = map[*regexp.Regexp]string{ + codeBlockRegex: "
$1
", + italicRegex: "$1$2$3", + boldRegex: "$1$2$3", + strikethroughRegex: "$1$2$3", +} + +func (portal *Portal) ParseWhatsAppFormat(input string) string { + output := html.EscapeString(input) + for regex, replacement := range whatsAppFormat { + output = regex.ReplaceAllString(output, replacement) + } + return output } func (portal *Portal) HandleTextMessage(message whatsapp.TextMessage) { @@ -322,8 +343,15 @@ func (portal *Portal) HandleTextMessage(message whatsapp.TextMessage) { Body: message.Text, MsgType: gomatrix.MsgText, } + + htmlBody := portal.ParseWhatsAppFormat(message.Text) + if htmlBody != message.Text { + content.FormattedBody = htmlBody + content.Format = gomatrix.FormatHTML + } portal.SetReply(&content, message.Info) + intent.UserTyping(portal.MXID, false, 0) resp, err := intent.SendMassagedMessageEvent(portal.MXID, gomatrix.EventMessage, content, int64(message.Info.Timestamp*1000)) if err != nil { portal.log.Errorfln("Failed to handle message %s: %v", message.Info.Id, err) @@ -407,6 +435,7 @@ func (portal *Portal) HandleMediaMessage(download func() ([]byte, error), thumbn content.MsgType = gomatrix.MsgFile } + intent.UserTyping(portal.MXID, false, 0) resp, err := intent.SendMassagedMessageEvent(portal.MXID, gomatrix.EventMessage, content, int64(info.Timestamp*1000)) if err != nil { portal.log.Errorfln("Failed to handle message %s: %v", info.Id, err)