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.Avatar = iconID
|
||||||
guild.AvatarURL = id.ContentURI{}
|
guild.AvatarURL = id.ContentURI{}
|
||||||
if guild.Avatar != "" {
|
if guild.Avatar != "" {
|
||||||
var err error
|
// TODO direct media support
|
||||||
guild.AvatarURL, err = uploadAvatar(guild.bridge.Bot, discordgo.EndpointGuildIcon(guild.ID, iconID))
|
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 {
|
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
|
return true
|
||||||
}
|
}
|
||||||
|
guild.AvatarURL = copied.MXC
|
||||||
}
|
}
|
||||||
if guild.MXID != "" {
|
if guild.MXID != "" {
|
||||||
_, err := guild.bridge.Bot.SetRoomAvatar(guild.MXID, guild.AvatarURL)
|
_, 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
|
return
|
||||||
}
|
}
|
||||||
if msg.WebhookID != "" {
|
if msg.WebhookID != "" {
|
||||||
addWebhookMeta(converted, msg)
|
portal.addWebhookMeta(converted, msg)
|
||||||
}
|
}
|
||||||
converted.Content.Mentions = portal.convertDiscordMentions(msg, "", false)
|
converted.Content.Mentions = portal.convertDiscordMentions(msg, "", false)
|
||||||
converted.Content.SetEdit(existing[0].MXID)
|
converted.Content.SetEdit(existing[0].MXID)
|
||||||
@@ -2152,13 +2152,15 @@ func (portal *Portal) UpdateGroupDMAvatar(iconID string) bool {
|
|||||||
portal.AvatarSet = false
|
portal.AvatarSet = false
|
||||||
portal.AvatarURL = id.ContentURI{}
|
portal.AvatarURL = id.ContentURI{}
|
||||||
if portal.Avatar != "" {
|
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 {
|
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
|
return true
|
||||||
} else {
|
|
||||||
portal.AvatarURL = uri
|
|
||||||
}
|
}
|
||||||
|
portal.AvatarURL = copied.MXC
|
||||||
}
|
}
|
||||||
portal.updateRoomAvatar()
|
portal.updateRoomAvatar()
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -310,27 +310,38 @@ func (portal *Portal) convertDiscordMessage(ctx context.Context, intent *appserv
|
|||||||
}
|
}
|
||||||
if msg.WebhookID != "" {
|
if msg.WebhookID != "" {
|
||||||
for _, part := range parts {
|
for _, part := range parts {
|
||||||
addWebhookMeta(part, msg)
|
portal.addWebhookMeta(part, msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return parts
|
return parts
|
||||||
}
|
}
|
||||||
|
|
||||||
func addWebhookMeta(part *ConvertedMessage, msg *discordgo.Message) {
|
func (portal *Portal) addWebhookMeta(part *ConvertedMessage, msg *discordgo.Message) {
|
||||||
if msg.WebhookID == "" {
|
if msg.WebhookID == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if part.Extra == nil {
|
if part.Extra == nil {
|
||||||
part.Extra = make(map[string]any)
|
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{
|
part.Extra["fi.mau.discord.webhook_metadata"] = map[string]any{
|
||||||
"id": msg.WebhookID,
|
"id": msg.WebhookID,
|
||||||
"name": msg.Author.Username,
|
"name": msg.Author.Username,
|
||||||
"avatar_id": msg.Author.Avatar,
|
"avatar_id": msg.Author.Avatar,
|
||||||
"avatar_url": msg.Author.AvatarURL(""),
|
"avatar_url": msg.Author.AvatarURL(""),
|
||||||
|
"avatar_mxc": avatarURL.String(),
|
||||||
}
|
}
|
||||||
part.Extra["com.beeper.per_message_profile"] = map[string]any{
|
part.Extra["com.beeper.per_message_profile"] = map[string]any{
|
||||||
"avatar_url": msg.Author.AvatarURL(""),
|
"avatar_url": avatarURL.String(),
|
||||||
"displayname": msg.Author.Username,
|
"displayname": msg.Author.Username,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
51
puppet.go
51
puppet.go
@@ -228,33 +228,44 @@ func (puppet *Puppet) UpdateName(info *discordgo.User) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (puppet *Puppet) UpdateAvatar(info *discordgo.User) bool {
|
func (br *DiscordBridge) reuploadUserAvatar(intent *appservice.IntentAPI, userID, avatarID string) (id.ContentURI, error) {
|
||||||
if puppet.IsWebhook && !puppet.bridge.Config.Bridge.EnableWebhookAvatars {
|
downloadURL := discordgo.EndpointUserAvatar(userID, avatarID)
|
||||||
info.Avatar = ""
|
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
|
return false
|
||||||
}
|
}
|
||||||
avatarChanged := info.Avatar != puppet.Avatar
|
avatarChanged := avatarID != puppet.Avatar
|
||||||
puppet.Avatar = info.Avatar
|
puppet.Avatar = avatarID
|
||||||
puppet.AvatarSet = false
|
puppet.AvatarSet = false
|
||||||
puppet.AvatarURL = id.ContentURI{}
|
puppet.AvatarURL = id.ContentURI{}
|
||||||
|
|
||||||
if puppet.Avatar != "" && (puppet.AvatarURL.IsEmpty() || avatarChanged) {
|
if puppet.Avatar != "" && (puppet.AvatarURL.IsEmpty() || avatarChanged) {
|
||||||
downloadURL := discordgo.EndpointUserAvatar(info.ID, info.Avatar)
|
url, err := puppet.bridge.reuploadUserAvatar(puppet.DefaultIntent(), info.ID, puppet.Avatar)
|
||||||
ext := "png"
|
if err != nil {
|
||||||
if strings.HasPrefix(info.Avatar, "a_") {
|
puppet.log.Warn().Err(err).Str("avatar_id", puppet.Avatar).Msg("Failed to reupload user avatar")
|
||||||
downloadURL = discordgo.EndpointUserAvatarAnimated(info.ID, info.Avatar)
|
return true
|
||||||
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)
|
|
||||||
if err != nil {
|
|
||||||
puppet.log.Warn().Err(err).Str("avatar_id", puppet.Avatar).Msg("Failed to reupload user avatar")
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
puppet.AvatarURL = url
|
puppet.AvatarURL = url
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user