Implement channel name formatting and handle channel updates

This commit is contained in:
Gary Kramlich
2022-04-11 11:35:35 -05:00
parent defcfad701
commit 3629d7807c
6 changed files with 164 additions and 49 deletions

31
bridge/avatar.go Normal file
View File

@@ -0,0 +1,31 @@
package bridge
import (
"fmt"
"io"
"net/http"
"maunium.net/go/mautrix/appservice"
"maunium.net/go/mautrix/id"
)
func uploadAvatar(intent *appservice.IntentAPI, url string) (id.ContentURI, error) {
getResp, err := http.DefaultClient.Get(url)
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
}

View File

@@ -223,6 +223,7 @@ func (mh *matrixHandler) handleMembership(evt *event.Event) {
return
}
}
if isSelf {
portal.handleMatrixLeave(user)
} else if puppet != nil {

View File

@@ -171,44 +171,44 @@ func (p *Portal) MainIntent() *appservice.IntentAPI {
}
func (p *Portal) createMatrixRoom(user *User, channel *discordgo.Channel) error {
p.roomCreateLock.Lock()
defer p.roomCreateLock.Unlock()
// If we have a matrix id the room should exist so we have nothing to do.
if p.MXID != "" {
return nil
}
p.roomCreateLock.Lock()
defer p.roomCreateLock.Unlock()
p.Type = channel.Type
if p.Type == discordgo.ChannelTypeDM {
p.DMUser = channel.Recipients[0].ID
}
// If we have a matrix id the room should exist so we have nothing to do.
if p.MXID != "" {
return nil
}
intent := p.MainIntent()
if err := intent.EnsureRegistered(); err != nil {
return err
}
// if p.IsPrivateChat() {
p.Name = channel.Name
name, err := p.bridge.Config.Bridge.FormatChannelname(channel, user.Session)
if err != nil {
p.log.Warnfln("failed to format name, proceeding with generic name: %v", err)
p.Name = channel.Name
} else {
p.Name = name
}
p.Topic = channel.Topic
// TODO: get avatars figured out
// p.Avatar = puppet.Avatar
// p.AvatarURL = puppet.AvatarURL
// }
p.log.Infoln("Creating Matrix room for channel:", p.Portal.Key.ChannelID)
initialState := []*event.Event{}
creationContent := make(map[string]interface{})
// if !portal.bridge.Config.Bridge.FederateRooms {
creationContent["m.federate"] = false
// }
var invite []id.UserID
@@ -650,13 +650,9 @@ func (p *Portal) handleMatrixMessage(sender *User, evt *event.Event) {
}
func (p *Portal) handleMatrixLeave(sender *User) {
if p.IsPrivateChat() {
p.log.Debugln("User left private chat portal, cleaning up and deleting...")
p.delete()
p.cleanup(false)
return
}
p.log.Debugln("User left private chat portal, cleaning up and deleting...")
p.delete()
p.cleanup(false)
// TODO: figure out how to close a dm from the API.
@@ -977,3 +973,61 @@ func (p *Portal) handleMatrixRedaction(evt *event.Event) {
p.log.Warnfln("Failed to redact %s@%s: no event found", p.Key, evt.Redacts)
}
func (p *Portal) update(user *User, channel *discordgo.Channel) {
name, err := p.bridge.Config.Bridge.FormatChannelname(channel, user.Session)
if err != nil {
p.log.Warnln("Failed to format channel name, using existing:", err)
} else {
p.Name = name
}
intent := p.MainIntent()
if p.Name != name {
_, err = intent.SetRoomName(p.MXID, p.Name)
if err != nil {
p.log.Warnln("Failed to update room name:", err)
}
}
if p.Topic != channel.Topic {
p.Topic = channel.Topic
_, err = intent.SetRoomTopic(p.MXID, p.Topic)
if err != nil {
p.log.Warnln("Failed to update room topic:", err)
}
}
if p.Avatar != channel.Icon {
p.Avatar = channel.Icon
var url string
if p.Type == discordgo.ChannelTypeDM {
dmUser, err := user.Session.User(p.DMUser)
if err != nil {
p.log.Warnln("failed to lookup the dmuser", err)
} else {
url = dmUser.AvatarURL("")
}
} else {
url = discordgo.EndpointGroupIcon(channel.ID, channel.Icon)
}
p.AvatarURL = id.ContentURI{}
if url != "" {
uri, err := uploadAvatar(intent, url)
if err != nil {
p.log.Warnf("failed to upload avatar", err)
} else {
p.AvatarURL = uri
}
}
intent.SetRoomAvatar(p.MXID, p.AvatarURL)
}
p.Update()
p.log.Debugln("portal updated")
}

View File

@@ -2,8 +2,6 @@ package bridge
import (
"fmt"
"io"
"net/http"
"regexp"
"sync"
@@ -209,27 +207,6 @@ func (p *Puppet) updatePortalName() {
})
}
func (p *Puppet) uploadAvatar(intent *appservice.IntentAPI, url string) (id.ContentURI, error) {
getResp, err := http.DefaultClient.Get(url)
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
}
func (p *Puppet) updateAvatar(source *User) bool {
user, err := source.Session.User(p.ID)
if err != nil {
@@ -248,7 +225,7 @@ func (p *Puppet) updateAvatar(source *User) bool {
return false
}
url, err := p.uploadAvatar(p.DefaultIntent(), user.AvatarURL(""))
url, err := uploadAvatar(p.DefaultIntent(), user.AvatarURL(""))
if err != nil {
p.log.Warnln("Failed to upload user avatar:", err)

View File

@@ -540,12 +540,7 @@ func (u *User) channelUpdateHandler(s *discordgo.Session, c *discordgo.ChannelUp
key := database.NewPortalKey(c.ID, u.User.ID)
portal := u.bridge.GetPortalByID(key)
portal.Name = c.Name
portal.Topic = c.Topic
u.log.Debugln("channel icon", c.Icon)
portal.Update()
u.log.Debugln("channel update")
portal.update(u, c.Channel)
}
func (u *User) messageCreateHandler(s *discordgo.Session, m *discordgo.MessageCreate) {