Add Matrix->Discord mention bridging
This commit is contained in:
62
formatter.go
62
formatter.go
@@ -6,6 +6,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/yuin/goldmark"
|
"github.com/yuin/goldmark"
|
||||||
|
"maunium.net/go/mautrix/id"
|
||||||
|
|
||||||
"maunium.net/go/mautrix/event"
|
"maunium.net/go/mautrix/event"
|
||||||
"maunium.net/go/mautrix/format"
|
"maunium.net/go/mautrix/format"
|
||||||
@@ -23,8 +24,55 @@ func renderDiscordMarkdown(text string) event.MessageEventContent {
|
|||||||
return format.RenderMarkdownCustom(text, mdRenderer)
|
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{
|
var matrixHTMLParser = &format.HTMLParser{
|
||||||
PillConverter: nil,
|
|
||||||
TabsToSpaces: 4,
|
TabsToSpaces: 4,
|
||||||
Newline: "\n",
|
Newline: "\n",
|
||||||
HorizontalLine: "\n---\n",
|
HorizontalLine: "\n---\n",
|
||||||
@@ -45,6 +93,10 @@ var matrixHTMLParser = &format.HTMLParser{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
matrixHTMLParser.PillConverter = pillConverter
|
||||||
|
}
|
||||||
|
|
||||||
var discordMarkdownEscaper = strings.NewReplacer(
|
var discordMarkdownEscaper = strings.NewReplacer(
|
||||||
`\`, `\\`,
|
`\`, `\\`,
|
||||||
`_`, `\_`,
|
`_`, `\_`,
|
||||||
@@ -52,11 +104,15 @@ var discordMarkdownEscaper = strings.NewReplacer(
|
|||||||
`~`, `\~`,
|
`~`, `\~`,
|
||||||
"`", "\\`",
|
"`", "\\`",
|
||||||
`|`, `\|`,
|
`|`, `\|`,
|
||||||
|
`<`, `\<`,
|
||||||
)
|
)
|
||||||
|
|
||||||
func parseMatrixHTML(content *event.MessageEventContent) string {
|
func (portal *Portal) parseMatrixHTML(user *User, content *event.MessageEventContent) string {
|
||||||
if content.Format == event.FormatHTML && len(content.FormattedBody) > 0 {
|
if content.Format == event.FormatHTML && len(content.FormattedBody) > 0 {
|
||||||
return matrixHTMLParser.Parse(content.FormattedBody, make(format.Context))
|
return matrixHTMLParser.Parse(content.FormattedBody, format.Context{
|
||||||
|
formatterContextUserKey: user,
|
||||||
|
formatterContextPortalKey: portal,
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
return discordMarkdownEscaper.Replace(content.Body)
|
return discordMarkdownEscaper.Replace(content.Body)
|
||||||
}
|
}
|
||||||
|
|||||||
13
portal.go
13
portal.go
@@ -929,9 +929,10 @@ func (portal *Portal) handleMatrixMessage(sender *User, evt *event.Event) {
|
|||||||
if editMXID := content.GetRelatesTo().GetReplaceID(); editMXID != "" && content.NewContent != nil {
|
if editMXID := content.GetRelatesTo().GetReplaceID(); editMXID != "" && content.NewContent != nil {
|
||||||
edits := portal.bridge.DB.Message.GetByMXID(portal.Key, editMXID)
|
edits := portal.bridge.DB.Message.GetByMXID(portal.Key, editMXID)
|
||||||
if edits != nil {
|
if edits != nil {
|
||||||
|
discordContent := portal.parseMatrixHTML(sender, content.NewContent)
|
||||||
// we don't have anything to save for the update message right now
|
// we don't have anything to save for the update message right now
|
||||||
// as we're not tracking edited timestamps.
|
// as we're not tracking edited timestamps.
|
||||||
_, err := sender.Session.ChannelMessageEdit(edits.DiscordProtoChannelID(), edits.DiscordID, parseMatrixHTML(content.NewContent))
|
_, err := sender.Session.ChannelMessageEdit(edits.DiscordProtoChannelID(), edits.DiscordID, discordContent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
portal.log.Errorln("Failed to update message %s: %v", edits.DiscordID, err)
|
portal.log.Errorln("Failed to update message %s: %v", edits.DiscordID, err)
|
||||||
}
|
}
|
||||||
@@ -966,7 +967,7 @@ func (portal *Portal) handleMatrixMessage(sender *User, evt *event.Event) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sendReq.Content = parseMatrixHTML(content)
|
sendReq.Content = portal.parseMatrixHTML(sender, content)
|
||||||
case event.MsgAudio, event.MsgFile, event.MsgImage, event.MsgVideo:
|
case event.MsgAudio, event.MsgFile, event.MsgImage, event.MsgVideo:
|
||||||
data, err := portal.downloadMatrixAttachment(evt.ID, content)
|
data, err := portal.downloadMatrixAttachment(evt.ID, content)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1289,15 +1290,15 @@ func (portal *Portal) handleDiscordReaction(user *User, reaction *discordgo.Mess
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (portal *Portal) handleMatrixRedaction(user *User, evt *event.Event) {
|
func (portal *Portal) handleMatrixRedaction(sender *User, evt *event.Event) {
|
||||||
if user.DiscordID != portal.Key.Receiver {
|
if portal.IsPrivateChat() && sender.DiscordID != portal.Key.Receiver {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// First look if we're redacting a message
|
// First look if we're redacting a message
|
||||||
message := portal.bridge.DB.Message.GetByMXID(portal.Key, evt.Redacts)
|
message := portal.bridge.DB.Message.GetByMXID(portal.Key, evt.Redacts)
|
||||||
if message != nil {
|
if message != nil {
|
||||||
err := user.Session.ChannelMessageDelete(message.DiscordProtoChannelID(), message.DiscordID)
|
err := sender.Session.ChannelMessageDelete(message.DiscordProtoChannelID(), message.DiscordID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
portal.log.Debugfln("Failed to delete discord message %s: %v", message.DiscordID, err)
|
portal.log.Debugfln("Failed to delete discord message %s: %v", message.DiscordID, err)
|
||||||
} else {
|
} else {
|
||||||
@@ -1309,7 +1310,7 @@ func (portal *Portal) handleMatrixRedaction(user *User, evt *event.Event) {
|
|||||||
// Now check if it's a reaction.
|
// Now check if it's a reaction.
|
||||||
reaction := portal.bridge.DB.Reaction.GetByMXID(evt.Redacts)
|
reaction := portal.bridge.DB.Reaction.GetByMXID(evt.Redacts)
|
||||||
if reaction != nil && reaction.Channel == portal.Key {
|
if reaction != nil && reaction.Channel == portal.Key {
|
||||||
err := user.Session.MessageReactionRemove(reaction.DiscordProtoChannelID(), reaction.MessageID, reaction.EmojiName, reaction.Sender)
|
err := sender.Session.MessageReactionRemove(reaction.DiscordProtoChannelID(), reaction.MessageID, reaction.EmojiName, reaction.Sender)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
portal.log.Debugfln("Failed to delete reaction %s from %s: %v", reaction.EmojiName, reaction.MessageID, err)
|
portal.log.Debugfln("Failed to delete reaction %s from %s: %v", reaction.EmojiName, reaction.MessageID, err)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user