Эх сурвалжийг харах

Include guild profiles in custom event field

Tulir Asokan 2 жил өмнө
parent
commit
e6108cb25d
4 өөрчлөгдсөн 77 нэмэгдсэн , 22 устгасан
  1. 1 1
      backfill.go
  2. 5 5
      portal.go
  3. 53 8
      portal_convert.go
  4. 18 8
      puppet.go

+ 1 - 1
backfill.go

@@ -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}

+ 5 - 5
portal.go

@@ -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

+ 53 - 8
portal_convert.go

@@ -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,
 	}

+ 18 - 8
puppet.go

@@ -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