86
portal.go
86
portal.go
@@ -1305,6 +1305,61 @@ func (portal *Portal) getRelayUserMeta(sender *User) (name, avatarURL string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const replyEmbedMaxLines = 1
|
||||||
|
const replyEmbedMaxChars = 72
|
||||||
|
|
||||||
|
func cutBody(body string) string {
|
||||||
|
lines := strings.Split(strings.TrimSpace(body), "\n")
|
||||||
|
var output string
|
||||||
|
for i, line := range lines {
|
||||||
|
if i >= replyEmbedMaxLines {
|
||||||
|
output += " […]"
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if i > 0 {
|
||||||
|
output += "\n"
|
||||||
|
}
|
||||||
|
output += line
|
||||||
|
if len(output) > replyEmbedMaxChars {
|
||||||
|
output = output[:replyEmbedMaxChars] + "…"
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
func (portal *Portal) convertReplyMessageToEmbed(eventID id.EventID, url string) (*discordgo.MessageEmbed, error) {
|
||||||
|
evt, err := portal.MainIntent().GetEvent(portal.MXID, eventID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to fetch event: %w", err)
|
||||||
|
}
|
||||||
|
err = evt.Content.ParseRaw(evt.Type)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to parse event content: %w", err)
|
||||||
|
}
|
||||||
|
content, ok := evt.Content.Parsed.(*event.MessageEventContent)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("unsupported event type %s / %T", evt.Type.String(), evt.Content.Parsed)
|
||||||
|
}
|
||||||
|
content.RemoveReplyFallback()
|
||||||
|
var targetUser string
|
||||||
|
|
||||||
|
puppet := portal.bridge.GetPuppetByMXID(evt.Sender)
|
||||||
|
if puppet != nil {
|
||||||
|
targetUser = fmt.Sprintf("<@%s>", puppet.ID)
|
||||||
|
} else if user := portal.bridge.GetUserByMXID(evt.Sender); user != nil && user.DiscordID != "" {
|
||||||
|
targetUser = fmt.Sprintf("<@%s>", user.DiscordID)
|
||||||
|
} else if member := portal.bridge.StateStore.GetMember(portal.MXID, evt.Sender); member != nil && member.Displayname != "" {
|
||||||
|
targetUser = member.Displayname
|
||||||
|
} else {
|
||||||
|
targetUser = evt.Sender.String()
|
||||||
|
}
|
||||||
|
body := escapeDiscordMarkdown(cutBody(content.Body))
|
||||||
|
body = fmt.Sprintf("**[Replying to](%s) %s**\n%s", url, targetUser, body)
|
||||||
|
embed := &discordgo.MessageEmbed{Description: body}
|
||||||
|
return embed, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (portal *Portal) handleMatrixMessage(sender *User, evt *event.Event) {
|
func (portal *Portal) handleMatrixMessage(sender *User, evt *event.Event) {
|
||||||
if portal.IsPrivateChat() && sender.DiscordID != portal.Key.Receiver {
|
if portal.IsPrivateChat() && sender.DiscordID != portal.Key.Receiver {
|
||||||
go portal.sendMessageMetrics(evt, errUserNotReceiver, "Ignoring")
|
go portal.sendMessageMetrics(evt, errUserNotReceiver, "Ignoring")
|
||||||
@@ -1323,6 +1378,7 @@ func (portal *Portal) handleMatrixMessage(sender *User, evt *event.Event) {
|
|||||||
go portal.sendMessageMetrics(evt, errUserNotLoggedIn, "Ignoring")
|
go portal.sendMessageMetrics(evt, errUserNotLoggedIn, "Ignoring")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
isWebhookSend := sess == nil
|
||||||
var threadID string
|
var threadID string
|
||||||
|
|
||||||
if editMXID := content.GetRelatesTo().GetReplaceID(); editMXID != "" && content.NewContent != nil {
|
if editMXID := content.GetRelatesTo().GetReplaceID(); editMXID != "" && content.NewContent != nil {
|
||||||
@@ -1330,7 +1386,7 @@ func (portal *Portal) handleMatrixMessage(sender *User, evt *event.Event) {
|
|||||||
if edits != nil {
|
if edits != nil {
|
||||||
discordContent, allowedMentions := portal.parseMatrixHTML(content.NewContent)
|
discordContent, allowedMentions := portal.parseMatrixHTML(content.NewContent)
|
||||||
var err error
|
var err error
|
||||||
if sess != nil {
|
if !isWebhookSend {
|
||||||
// TODO save edit in message table
|
// TODO save edit in message table
|
||||||
_, err = sess.ChannelMessageEdit(edits.DiscordProtoChannelID(), edits.DiscordID, discordContent)
|
_, err = sess.ChannelMessageEdit(edits.DiscordProtoChannelID(), edits.DiscordID, discordContent)
|
||||||
} else {
|
} else {
|
||||||
@@ -1349,7 +1405,7 @@ func (portal *Portal) handleMatrixMessage(sender *User, evt *event.Event) {
|
|||||||
if existingThread != nil {
|
if existingThread != nil {
|
||||||
threadID = existingThread.ID
|
threadID = existingThread.ID
|
||||||
} else {
|
} else {
|
||||||
if sess == nil {
|
if isWebhookSend {
|
||||||
// TODO start thread with bot?
|
// TODO start thread with bot?
|
||||||
go portal.sendMessageMetrics(evt, errCantStartThread, "Dropping")
|
go portal.sendMessageMetrics(evt, errCantStartThread, "Dropping")
|
||||||
return
|
return
|
||||||
@@ -1378,17 +1434,27 @@ func (portal *Portal) handleMatrixMessage(sender *User, evt *event.Event) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch content.MsgType {
|
if replyToMXID := content.RelatesTo.GetNonFallbackReplyTo(); replyToMXID != "" {
|
||||||
case event.MsgText, event.MsgEmote, event.MsgNotice:
|
replyTo := portal.bridge.DB.Message.GetByMXID(portal.Key, replyToMXID)
|
||||||
if replyToMXID := content.RelatesTo.GetNonFallbackReplyTo(); replyToMXID != "" {
|
if replyTo != nil && replyTo.ThreadID == threadID {
|
||||||
replyTo := portal.bridge.DB.Message.GetByMXID(portal.Key, replyToMXID)
|
if isWebhookSend {
|
||||||
if replyTo != nil && replyTo.ThreadID == threadID {
|
messageURL := fmt.Sprintf("https://discord.com/channels/%s/%s/%s", portal.GuildID, channelID, replyTo.DiscordID)
|
||||||
|
embed, err := portal.convertReplyMessageToEmbed(replyTo.MXID, messageURL)
|
||||||
|
if err != nil {
|
||||||
|
portal.log.Warn().Err(err).Msg("Failed to convert reply message to embed for webhook send")
|
||||||
|
} else if embed != nil {
|
||||||
|
sendReq.Embeds = []*discordgo.MessageEmbed{embed}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
sendReq.Reference = &discordgo.MessageReference{
|
sendReq.Reference = &discordgo.MessageReference{
|
||||||
ChannelID: channelID,
|
ChannelID: channelID,
|
||||||
MessageID: replyTo.DiscordID,
|
MessageID: replyTo.DiscordID,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
switch content.MsgType {
|
||||||
|
case event.MsgText, event.MsgEmote, event.MsgNotice:
|
||||||
sendReq.Content, sendReq.AllowedMentions = portal.parseMatrixHTML(content)
|
sendReq.Content, sendReq.AllowedMentions = portal.parseMatrixHTML(content)
|
||||||
case event.MsgAudio, event.MsgFile, event.MsgImage, event.MsgVideo:
|
case event.MsgAudio, event.MsgFile, event.MsgImage, event.MsgVideo:
|
||||||
data, err := downloadMatrixAttachment(portal.MainIntent(), content)
|
data, err := downloadMatrixAttachment(portal.MainIntent(), content)
|
||||||
@@ -1402,7 +1468,7 @@ func (portal *Portal) handleMatrixMessage(sender *User, evt *event.Event) {
|
|||||||
sendReq.Content, sendReq.AllowedMentions = portal.parseMatrixHTML(content)
|
sendReq.Content, sendReq.AllowedMentions = portal.parseMatrixHTML(content)
|
||||||
}
|
}
|
||||||
|
|
||||||
if sess != nil && sess.IsUser {
|
if !isWebhookSend && sess.IsUser {
|
||||||
att := &discordgo.MessageAttachment{
|
att := &discordgo.MessageAttachment{
|
||||||
ID: "0",
|
ID: "0",
|
||||||
Filename: filename,
|
Filename: filename,
|
||||||
@@ -1438,7 +1504,7 @@ func (portal *Portal) handleMatrixMessage(sender *User, evt *event.Event) {
|
|||||||
go portal.sendMessageMetrics(evt, fmt.Errorf("%w %q", errUnknownMsgType, content.MsgType), "Ignoring")
|
go portal.sendMessageMetrics(evt, fmt.Errorf("%w %q", errUnknownMsgType, content.MsgType), "Ignoring")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if sess != nil {
|
if !isWebhookSend {
|
||||||
// AllowedMentions must not be set for real users, and it's also not that useful for personal bots.
|
// AllowedMentions must not be set for real users, and it's also not that useful for personal bots.
|
||||||
// It's only important for relaying, where the webhook may have higher permissions than the user on Matrix.
|
// It's only important for relaying, where the webhook may have higher permissions than the user on Matrix.
|
||||||
sendReq.AllowedMentions = nil
|
sendReq.AllowedMentions = nil
|
||||||
@@ -1455,7 +1521,7 @@ func (portal *Portal) handleMatrixMessage(sender *User, evt *event.Event) {
|
|||||||
sendReq.Nonce = generateNonce()
|
sendReq.Nonce = generateNonce()
|
||||||
var msg *discordgo.Message
|
var msg *discordgo.Message
|
||||||
var err error
|
var err error
|
||||||
if sess != nil {
|
if !isWebhookSend {
|
||||||
msg, err = sess.ChannelMessageSendComplex(channelID, &sendReq)
|
msg, err = sess.ChannelMessageSendComplex(channelID, &sendReq)
|
||||||
} else {
|
} else {
|
||||||
username, avatarURL := portal.getRelayUserMeta(sender)
|
username, avatarURL := portal.getRelayUserMeta(sender)
|
||||||
|
|||||||
Reference in New Issue
Block a user