Include guild profiles in custom event field

This commit is contained in:
Tulir Asokan
2023-05-27 14:40:51 +03:00
parent d004aea9cb
commit e6108cb25d
4 changed files with 77 additions and 22 deletions

View File

@@ -226,7 +226,7 @@ func (portal *Portal) convertMessageBatch(log zerolog.Logger, source *User, mess
Int("message_type", int(msg.Type)).
Str("author_id", msg.Author.ID).
Logger()
parts := portal.convertDiscordMessage(log.WithContext(ctx), intent, msg)
parts := portal.convertDiscordMessage(log.WithContext(ctx), puppet, intent, msg)
for i, part := range parts {
if replyTo != nil {
part.Content.RelatesTo = &event.RelatesTo{InReplyTo: replyTo}

View File

@@ -638,7 +638,7 @@ func (portal *Portal) handleDiscordMessageCreate(user *User, msg *discordgo.Mess
mentions := portal.convertDiscordMentions(msg, replySenderMXID, true)
ts, _ := discordgo.SnowflakeTimestamp(msg.ID)
parts := portal.convertDiscordMessage(ctx, intent, msg)
parts := portal.convertDiscordMessage(ctx, puppet, intent, msg)
dbParts := make([]database.MessagePart, 0, len(parts))
for i, part := range parts {
if (replyTo != nil || threadRootEvent != "") && part.Content.RelatesTo == nil {
@@ -844,7 +844,8 @@ func (portal *Portal) handleDiscordMessageUpdate(user *User, msg *discordgo.Mess
return
}
intent := portal.bridge.GetPuppetByID(msg.Author.ID).IntentFor(portal)
puppet := portal.bridge.GetPuppetByID(msg.Author.ID)
intent := puppet.IntentFor(portal)
attachmentMap := map[string]*database.Message{}
for _, existingPart := range existing {
@@ -897,9 +898,8 @@ func (portal *Portal) handleDiscordMessageUpdate(user *User, msg *discordgo.Mess
Msg("Dropping non-text edit")
return
}
if msg.WebhookID != "" {
portal.addWebhookMeta(converted, msg)
}
puppet.addWebhookMeta(converted, msg)
puppet.addMemberMeta(converted, msg)
converted.Content.Mentions = portal.convertDiscordMentions(msg, "", false)
converted.Content.SetEdit(existing[0].MXID)
// Never actually mention new users of edits, only include mentions inside m.new_content

View File

@@ -257,7 +257,7 @@ func (portal *Portal) convertDiscordVideoEmbed(ctx context.Context, intent *apps
}
}
func (portal *Portal) convertDiscordMessage(ctx context.Context, intent *appservice.IntentAPI, msg *discordgo.Message) []*ConvertedMessage {
func (portal *Portal) convertDiscordMessage(ctx context.Context, puppet *Puppet, intent *appservice.IntentAPI, msg *discordgo.Message) []*ConvertedMessage {
predictedLength := len(msg.Attachments) + len(msg.StickerItems)
if msg.Content != "" {
predictedLength++
@@ -308,15 +308,58 @@ func (portal *Portal) convertDiscordMessage(ctx context.Context, intent *appserv
parts = append(parts, part)
}
}
if msg.WebhookID != "" {
for _, part := range parts {
portal.addWebhookMeta(part, msg)
}
for _, part := range parts {
puppet.addWebhookMeta(part, msg)
puppet.addMemberMeta(part, msg)
}
return parts
}
func (portal *Portal) addWebhookMeta(part *ConvertedMessage, msg *discordgo.Message) {
func (puppet *Puppet) addMemberMeta(part *ConvertedMessage, msg *discordgo.Message) {
if msg.Member == nil {
return
}
if part.Extra == nil {
part.Extra = make(map[string]any)
}
var avatarURL id.ContentURI
if msg.Member.Avatar != "" {
var err error
avatarURL, err = puppet.bridge.reuploadUserAvatar(puppet.DefaultIntent(), msg.GuildID, msg.Author.ID, msg.Author.Avatar)
if err != nil {
puppet.log.Warn().Err(err).
Str("avatar_id", msg.Author.Avatar).
Msg("Failed to reupload guild user avatar")
}
}
var discordAvararURL string
if msg.Member.Avatar != "" {
discordAvararURL = msg.Member.AvatarURL("")
}
part.Extra["fi.mau.discord.guild_member_metadata"] = map[string]any{
"nick": msg.Member.Nick,
"avatar_id": msg.Member.Avatar,
"avatar_url": discordAvararURL,
"avatar_mxc": avatarURL.String(),
}
if msg.Member.Nick != "" || !avatarURL.IsEmpty() {
perMessageProfile := map[string]any{
"is_multiple_users": false,
"displayname": msg.Member.Nick,
"avatar_url": avatarURL.String(),
}
if msg.Member.Nick == "" {
perMessageProfile["displayname"] = puppet.Name
}
if avatarURL.IsEmpty() {
perMessageProfile["avatar_url"] = puppet.AvatarURL.String()
}
part.Extra["com.beeper.per_message_profile"] = perMessageProfile
}
}
func (puppet *Puppet) addWebhookMeta(part *ConvertedMessage, msg *discordgo.Message) {
if msg.WebhookID == "" {
return
}
@@ -326,9 +369,9 @@ func (portal *Portal) addWebhookMeta(part *ConvertedMessage, msg *discordgo.Mess
var avatarURL id.ContentURI
if msg.Author.Avatar != "" {
var err error
avatarURL, err = portal.bridge.reuploadUserAvatar(portal.MainIntent(), msg.Author.ID, msg.Author.Avatar)
avatarURL, err = puppet.bridge.reuploadUserAvatar(puppet.DefaultIntent(), "", msg.Author.ID, msg.Author.Avatar)
if err != nil {
portal.log.Warn().Err(err).
puppet.log.Warn().Err(err).
Str("avatar_id", msg.Author.Avatar).
Msg("Failed to reupload webhook avatar")
}
@@ -341,6 +384,8 @@ func (portal *Portal) addWebhookMeta(part *ConvertedMessage, msg *discordgo.Mess
"avatar_mxc": avatarURL.String(),
}
part.Extra["com.beeper.per_message_profile"] = map[string]any{
"is_multiple_users": true,
"avatar_url": avatarURL.String(),
"displayname": msg.Author.Username,
}

View File

@@ -228,19 +228,29 @@ func (puppet *Puppet) UpdateName(info *discordgo.User) bool {
return true
}
func (br *DiscordBridge) reuploadUserAvatar(intent *appservice.IntentAPI, userID, avatarID string) (id.ContentURI, error) {
downloadURL := discordgo.EndpointUserAvatar(userID, avatarID)
ext := "png"
if strings.HasPrefix(avatarID, "a_") {
downloadURL = discordgo.EndpointUserAvatarAnimated(userID, avatarID)
ext = "gif"
func (br *DiscordBridge) reuploadUserAvatar(intent *appservice.IntentAPI, guildID, userID, avatarID string) (id.ContentURI, error) {
var downloadURL, ext string
if guildID == "" {
downloadURL = discordgo.EndpointUserAvatar(userID, avatarID)
ext = "png"
if strings.HasPrefix(avatarID, "a_") {
downloadURL = discordgo.EndpointUserAvatarAnimated(userID, avatarID)
ext = "gif"
}
} else {
downloadURL = discordgo.EndpointGuildMemberAvatar(guildID, userID, avatarID)
ext = "png"
if strings.HasPrefix(avatarID, "a_") {
downloadURL = discordgo.EndpointGuildMemberAvatarAnimated(guildID, userID, avatarID)
ext = "gif"
}
}
url := br.Config.Bridge.MediaPatterns.Avatar(userID, avatarID, ext)
if !url.IsEmpty() {
return url, nil
}
copied, err := br.copyAttachmentToMatrix(intent, downloadURL, false, AttachmentMeta{
AttachmentID: fmt.Sprintf("avatar/%s/%s", userID, avatarID),
AttachmentID: fmt.Sprintf("avatar/%s/%s/%s", guildID, userID, avatarID),
})
if err != nil {
return url, err
@@ -262,7 +272,7 @@ func (puppet *Puppet) UpdateAvatar(info *discordgo.User) bool {
puppet.AvatarURL = id.ContentURI{}
if puppet.Avatar != "" && (puppet.AvatarURL.IsEmpty() || avatarChanged) {
url, err := puppet.bridge.reuploadUserAvatar(puppet.DefaultIntent(), info.ID, puppet.Avatar)
url, err := puppet.bridge.reuploadUserAvatar(puppet.DefaultIntent(), "", info.ID, puppet.Avatar)
if err != nil {
puppet.log.Warn().Err(err).Str("avatar_id", puppet.Avatar).Msg("Failed to reupload user avatar")
return true