120 lines
3.4 KiB
Go
120 lines
3.4 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"github.com/yuin/goldmark"
|
|
"maunium.net/go/mautrix/id"
|
|
|
|
"maunium.net/go/mautrix/event"
|
|
"maunium.net/go/mautrix/format"
|
|
"maunium.net/go/mautrix/format/mdext"
|
|
)
|
|
|
|
var mdRenderer = goldmark.New(format.Extensions, format.HTMLOptions,
|
|
goldmark.WithExtensions(mdext.EscapeHTML, mdext.SimpleSpoiler, mdext.DiscordUnderline))
|
|
var escapeFixer = regexp.MustCompile(`\\(__[^_]|\*\*[^*])`)
|
|
|
|
func renderDiscordMarkdown(text string) event.MessageEventContent {
|
|
text = escapeFixer.ReplaceAllStringFunc(text, func(s string) string {
|
|
return s[:2] + `\` + s[2:]
|
|
})
|
|
return format.RenderMarkdownCustom(text, mdRenderer)
|
|
}
|
|
|
|
const formatterContextUserKey = "fi.mau.discord.user"
|
|
const formatterContextPortalKey = "fi.mau.discord.portal"
|
|
|
|
func pillConverter(displayname, mxid, eventID string, ctx format.Context) string {
|
|
if len(mxid) == 0 {
|
|
return displayname
|
|
}
|
|
user := ctx[formatterContextUserKey].(*User)
|
|
if mxid[0] == '#' {
|
|
alias, err := user.bridge.Bot.ResolveAlias(id.RoomAlias(mxid))
|
|
if err != nil {
|
|
return displayname
|
|
}
|
|
mxid = alias.RoomID.String()
|
|
}
|
|
if mxid[0] == '!' {
|
|
portal := user.bridge.GetPortalByMXID(id.RoomID(mxid))
|
|
if portal != nil {
|
|
if eventID == "" {
|
|
//currentPortal := ctx[formatterContextPortalKey].(*Portal)
|
|
return fmt.Sprintf("<#%s>", portal.Key.ChannelID)
|
|
//if currentPortal.GuildID == portal.GuildID {
|
|
//} else if portal.GuildID != "" {
|
|
// return fmt.Sprintf("<#%s:%s:%s>", portal.Key.ChannelID, portal.GuildID, portal.Name)
|
|
//} else {
|
|
// // TODO is mentioning private channels possible at all?
|
|
//}
|
|
} else if msg := user.bridge.DB.Message.GetByMXID(portal.Key, id.EventID(eventID)); msg != nil {
|
|
guildID := portal.GuildID
|
|
if guildID == "" {
|
|
guildID = "@me"
|
|
}
|
|
return fmt.Sprintf("https://discord.com/channels/%s/%s/%s", guildID, msg.DiscordProtoChannelID(), msg.DiscordID)
|
|
}
|
|
}
|
|
} else if mxid[0] == '@' {
|
|
parsedID, ok := user.bridge.ParsePuppetMXID(id.UserID(mxid))
|
|
if ok {
|
|
return fmt.Sprintf("<@%s>", parsedID)
|
|
}
|
|
mentionedUser := user.bridge.GetUserByMXID(id.UserID(mxid))
|
|
if mentionedUser != nil && mentionedUser.DiscordID != "" {
|
|
return fmt.Sprintf("<@%s>", mentionedUser.DiscordID)
|
|
}
|
|
}
|
|
return displayname
|
|
}
|
|
|
|
var matrixHTMLParser = &format.HTMLParser{
|
|
TabsToSpaces: 4,
|
|
Newline: "\n",
|
|
HorizontalLine: "\n---\n",
|
|
ItalicConverter: func(s string, context format.Context) string {
|
|
return fmt.Sprintf("*%s*", s)
|
|
},
|
|
UnderlineConverter: func(s string, context format.Context) string {
|
|
return fmt.Sprintf("__%s__", s)
|
|
},
|
|
TextConverter: func(s string, context format.Context) string {
|
|
return discordMarkdownEscaper.Replace(s)
|
|
},
|
|
SpoilerConverter: func(text, reason string, ctx format.Context) string {
|
|
if reason != "" {
|
|
return fmt.Sprintf("(%s) ||%s||", reason, text)
|
|
}
|
|
return fmt.Sprintf("||%s||", text)
|
|
},
|
|
}
|
|
|
|
func init() {
|
|
matrixHTMLParser.PillConverter = pillConverter
|
|
}
|
|
|
|
var discordMarkdownEscaper = strings.NewReplacer(
|
|
`\`, `\\`,
|
|
`_`, `\_`,
|
|
`*`, `\*`,
|
|
`~`, `\~`,
|
|
"`", "\\`",
|
|
`|`, `\|`,
|
|
`<`, `\<`,
|
|
)
|
|
|
|
func (portal *Portal) parseMatrixHTML(user *User, content *event.MessageEventContent) string {
|
|
if content.Format == event.FormatHTML && len(content.FormattedBody) > 0 {
|
|
return matrixHTMLParser.Parse(content.FormattedBody, format.Context{
|
|
formatterContextUserKey: user,
|
|
formatterContextPortalKey: portal,
|
|
})
|
|
} else {
|
|
return discordMarkdownEscaper.Replace(content.Body)
|
|
}
|
|
}
|