Reupload webhook avatars to fill custom metadata
This commit is contained in:
40
avatar.go
40
avatar.go
@@ -1,40 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"maunium.net/go/mautrix/appservice"
|
||||
"maunium.net/go/mautrix/id"
|
||||
|
||||
"github.com/bwmarrin/discordgo"
|
||||
)
|
||||
|
||||
func uploadAvatar(intent *appservice.IntentAPI, url string) (id.ContentURI, error) {
|
||||
req, err := http.NewRequest(http.MethodGet, url, nil)
|
||||
if err != nil {
|
||||
return id.ContentURI{}, fmt.Errorf("failed to prepare request: %w", err)
|
||||
}
|
||||
for key, value := range discordgo.DroidImageHeaders {
|
||||
req.Header.Set(key, value)
|
||||
}
|
||||
getResp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return id.ContentURI{}, fmt.Errorf("failed to download avatar: %w", err)
|
||||
}
|
||||
|
||||
data, err := io.ReadAll(getResp.Body)
|
||||
_ = getResp.Body.Close()
|
||||
if err != nil {
|
||||
return id.ContentURI{}, fmt.Errorf("failed to read avatar data: %w", err)
|
||||
}
|
||||
|
||||
mime := http.DetectContentType(data)
|
||||
resp, err := intent.UploadBytes(data, mime)
|
||||
if err != nil {
|
||||
return id.ContentURI{}, fmt.Errorf("failed to upload avatar to Matrix: %w", err)
|
||||
}
|
||||
|
||||
return resp.ContentURI, nil
|
||||
}
|
||||
@@ -272,12 +272,15 @@ func (guild *Guild) UpdateAvatar(iconID string) bool {
|
||||
guild.Avatar = iconID
|
||||
guild.AvatarURL = id.ContentURI{}
|
||||
if guild.Avatar != "" {
|
||||
var err error
|
||||
guild.AvatarURL, err = uploadAvatar(guild.bridge.Bot, discordgo.EndpointGuildIcon(guild.ID, iconID))
|
||||
// TODO direct media support
|
||||
copied, err := guild.bridge.copyAttachmentToMatrix(guild.bridge.Bot, discordgo.EndpointGuildIcon(guild.ID, iconID), false, AttachmentMeta{
|
||||
AttachmentID: fmt.Sprintf("guild_avatar/%s/%s", guild.ID, iconID),
|
||||
})
|
||||
if err != nil {
|
||||
guild.log.Warnfln("Failed to reupload guild avatar %s: %v", guild.Avatar, err)
|
||||
guild.log.Warnfln("Failed to reupload guild avatar %s: %v", iconID, err)
|
||||
return true
|
||||
}
|
||||
guild.AvatarURL = copied.MXC
|
||||
}
|
||||
if guild.MXID != "" {
|
||||
_, err := guild.bridge.Bot.SetRoomAvatar(guild.MXID, guild.AvatarURL)
|
||||
|
||||
12
portal.go
12
portal.go
@@ -898,7 +898,7 @@ func (portal *Portal) handleDiscordMessageUpdate(user *User, msg *discordgo.Mess
|
||||
return
|
||||
}
|
||||
if msg.WebhookID != "" {
|
||||
addWebhookMeta(converted, msg)
|
||||
portal.addWebhookMeta(converted, msg)
|
||||
}
|
||||
converted.Content.Mentions = portal.convertDiscordMentions(msg, "", false)
|
||||
converted.Content.SetEdit(existing[0].MXID)
|
||||
@@ -2152,13 +2152,15 @@ func (portal *Portal) UpdateGroupDMAvatar(iconID string) bool {
|
||||
portal.AvatarSet = false
|
||||
portal.AvatarURL = id.ContentURI{}
|
||||
if portal.Avatar != "" {
|
||||
uri, err := uploadAvatar(portal.MainIntent(), discordgo.EndpointGroupIcon(portal.Key.ChannelID, portal.Avatar))
|
||||
// TODO direct media support
|
||||
copied, err := portal.bridge.copyAttachmentToMatrix(portal.MainIntent(), discordgo.EndpointGroupIcon(portal.Key.ChannelID, portal.Avatar), false, AttachmentMeta{
|
||||
AttachmentID: fmt.Sprintf("private_channel_avatar/%s/%s", portal.Key.ChannelID, iconID),
|
||||
})
|
||||
if err != nil {
|
||||
portal.log.Err(err).Str("avatar_id", portal.Avatar).Msg("Failed to reupload channel avatar")
|
||||
portal.log.Err(err).Str("avatar_id", iconID).Msg("Failed to reupload channel avatar")
|
||||
return true
|
||||
} else {
|
||||
portal.AvatarURL = uri
|
||||
}
|
||||
portal.AvatarURL = copied.MXC
|
||||
}
|
||||
portal.updateRoomAvatar()
|
||||
return true
|
||||
|
||||
@@ -310,27 +310,38 @@ func (portal *Portal) convertDiscordMessage(ctx context.Context, intent *appserv
|
||||
}
|
||||
if msg.WebhookID != "" {
|
||||
for _, part := range parts {
|
||||
addWebhookMeta(part, msg)
|
||||
portal.addWebhookMeta(part, msg)
|
||||
}
|
||||
}
|
||||
return parts
|
||||
}
|
||||
|
||||
func addWebhookMeta(part *ConvertedMessage, msg *discordgo.Message) {
|
||||
func (portal *Portal) addWebhookMeta(part *ConvertedMessage, msg *discordgo.Message) {
|
||||
if msg.WebhookID == "" {
|
||||
return
|
||||
}
|
||||
if part.Extra == nil {
|
||||
part.Extra = make(map[string]any)
|
||||
}
|
||||
var avatarURL id.ContentURI
|
||||
if msg.Author.Avatar != "" {
|
||||
var err error
|
||||
avatarURL, err = portal.bridge.reuploadUserAvatar(portal.MainIntent(), msg.Author.ID, msg.Author.Avatar)
|
||||
if err != nil {
|
||||
portal.log.Warn().Err(err).
|
||||
Str("avatar_id", msg.Author.Avatar).
|
||||
Msg("Failed to reupload webhook avatar")
|
||||
}
|
||||
}
|
||||
part.Extra["fi.mau.discord.webhook_metadata"] = map[string]any{
|
||||
"id": msg.WebhookID,
|
||||
"name": msg.Author.Username,
|
||||
"avatar_id": msg.Author.Avatar,
|
||||
"avatar_url": msg.Author.AvatarURL(""),
|
||||
"avatar_mxc": avatarURL.String(),
|
||||
}
|
||||
part.Extra["com.beeper.per_message_profile"] = map[string]any{
|
||||
"avatar_url": msg.Author.AvatarURL(""),
|
||||
"avatar_url": avatarURL.String(),
|
||||
"displayname": msg.Author.Username,
|
||||
}
|
||||
}
|
||||
|
||||
45
puppet.go
45
puppet.go
@@ -228,34 +228,45 @@ func (puppet *Puppet) UpdateName(info *discordgo.User) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (puppet *Puppet) UpdateAvatar(info *discordgo.User) bool {
|
||||
if puppet.IsWebhook && !puppet.bridge.Config.Bridge.EnableWebhookAvatars {
|
||||
info.Avatar = ""
|
||||
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"
|
||||
}
|
||||
if puppet.Avatar == info.Avatar && puppet.AvatarSet {
|
||||
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),
|
||||
})
|
||||
if err != nil {
|
||||
return url, err
|
||||
}
|
||||
return copied.MXC, nil
|
||||
}
|
||||
|
||||
func (puppet *Puppet) UpdateAvatar(info *discordgo.User) bool {
|
||||
avatarID := info.Avatar
|
||||
if puppet.IsWebhook && !puppet.bridge.Config.Bridge.EnableWebhookAvatars {
|
||||
avatarID = ""
|
||||
}
|
||||
if puppet.Avatar == avatarID && puppet.AvatarSet {
|
||||
return false
|
||||
}
|
||||
avatarChanged := info.Avatar != puppet.Avatar
|
||||
puppet.Avatar = info.Avatar
|
||||
avatarChanged := avatarID != puppet.Avatar
|
||||
puppet.Avatar = avatarID
|
||||
puppet.AvatarSet = false
|
||||
puppet.AvatarURL = id.ContentURI{}
|
||||
|
||||
if puppet.Avatar != "" && (puppet.AvatarURL.IsEmpty() || avatarChanged) {
|
||||
downloadURL := discordgo.EndpointUserAvatar(info.ID, info.Avatar)
|
||||
ext := "png"
|
||||
if strings.HasPrefix(info.Avatar, "a_") {
|
||||
downloadURL = discordgo.EndpointUserAvatarAnimated(info.ID, info.Avatar)
|
||||
ext = "gif"
|
||||
}
|
||||
url := puppet.bridge.Config.Bridge.MediaPatterns.Avatar(info.ID, info.Avatar, ext)
|
||||
if url.IsEmpty() {
|
||||
var err error
|
||||
url, err = uploadAvatar(puppet.DefaultIntent(), downloadURL)
|
||||
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
|
||||
}
|
||||
}
|
||||
puppet.AvatarURL = url
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user