Add support for unbridging guilds

This commit is contained in:
Tulir Asokan
2023-01-13 17:01:23 +02:00
parent 856f9a40fa
commit 9d84faa954
4 changed files with 78 additions and 46 deletions

View File

@@ -56,6 +56,10 @@ func (pq *PortalQuery) GetAll() []*Portal {
return pq.getAll(portalSelect) return pq.getAll(portalSelect)
} }
func (pq *PortalQuery) GetAllInGuild(guildID string) []*Portal {
return pq.getAll(portalSelect+" WHERE dc_guild_id=$1", guildID)
}
func (pq *PortalQuery) GetByID(key PortalKey) *Portal { func (pq *PortalQuery) GetByID(key PortalKey) *Portal {
return pq.get(portalSelect+" WHERE dcid=$1 AND (receiver=$2 OR receiver='')", key.ChannelID, key.Receiver) return pq.get(portalSelect+" WHERE dcid=$1 AND (receiver=$2 OR receiver='')", key.ChannelID, key.Receiver)
} }

View File

@@ -17,6 +17,7 @@
package main package main
import ( import (
"errors"
"fmt" "fmt"
"sync" "sync"
@@ -285,3 +286,32 @@ func (guild *Guild) UpdateAvatar(iconID string) bool {
} }
return true return true
} }
func (guild *Guild) cleanup() {
if guild.MXID == "" {
return
}
intent := guild.bridge.Bot
if guild.bridge.SpecVersions.UnstableFeatures["com.beeper.room_yeeting"] {
err := intent.BeeperDeleteRoom(guild.MXID)
if err == nil || errors.Is(err, mautrix.MNotFound) {
return
}
guild.log.Warnfln("Failed to delete %s using hungryserv yeet endpoint, falling back to normal behavior: %v", guild.MXID, err)
}
guild.bridge.cleanupRoom(intent, guild.MXID, false, guild.log)
}
func (guild *Guild) RemoveMXID() {
guild.bridge.guildsLock.Lock()
defer guild.bridge.guildsLock.Unlock()
if guild.MXID == "" {
return
}
delete(guild.bridge.guildsByMXID, guild.MXID)
guild.MXID = ""
guild.AvatarSet = false
guild.NameSet = false
guild.AutoBridgeChannels = false
guild.Update()
}

View File

@@ -177,6 +177,10 @@ func (br *DiscordBridge) GetAllPortals() []*Portal {
return br.dbPortalsToPortals(br.DB.Portal.GetAll()) return br.dbPortalsToPortals(br.DB.Portal.GetAll())
} }
func (br *DiscordBridge) GetAllPortalsInGuild(guildID string) []*Portal {
return br.dbPortalsToPortals(br.DB.Portal.GetAllInGuild(guildID))
}
func (br *DiscordBridge) GetAllIPortals() (iportals []bridge.Portal) { func (br *DiscordBridge) GetAllIPortals() (iportals []bridge.Portal) {
portals := br.GetAllPortals() portals := br.GetAllPortals()
iportals = make([]bridge.Portal, len(portals)) iportals = make([]bridge.Portal, len(portals))
@@ -1291,6 +1295,12 @@ func (portal *Portal) RemoveMXID() {
} }
delete(portal.bridge.portalsByMXID, portal.MXID) delete(portal.bridge.portalsByMXID, portal.MXID)
portal.MXID = "" portal.MXID = ""
portal.AvatarSet = false
portal.NameSet = false
portal.TopicSet = false
portal.Encrypted = false
portal.InSpace = ""
portal.FirstEventID = ""
portal.Update() portal.Update()
portal.bridge.DB.Message.DeleteAll(portal.Key) portal.bridge.DB.Message.DeleteAll(portal.Key)
} }
@@ -1316,9 +1326,13 @@ func (portal *Portal) cleanup(puppetsOnly bool) {
return return
} }
members, err := intent.JoinedMembers(portal.MXID) portal.bridge.cleanupRoom(intent, portal.MXID, puppetsOnly, portal.log)
}
func (br *DiscordBridge) cleanupRoom(intent *appservice.IntentAPI, mxid id.RoomID, puppetsOnly bool, log log.Logger) {
members, err := intent.JoinedMembers(mxid)
if err != nil { if err != nil {
portal.log.Errorln("Failed to get portal members for cleanup:", err) log.Errorln("Failed to get portal members for cleanup:", err)
return return
} }
@@ -1327,23 +1341,23 @@ func (portal *Portal) cleanup(puppetsOnly bool) {
continue continue
} }
puppet := portal.bridge.GetPuppetByMXID(member) puppet := br.GetPuppetByMXID(member)
if puppet != nil { if puppet != nil {
_, err = puppet.DefaultIntent().LeaveRoom(portal.MXID) _, err = puppet.DefaultIntent().LeaveRoom(mxid)
if err != nil { if err != nil {
portal.log.Errorln("Error leaving as puppet while cleaning up portal:", err) log.Errorln("Error leaving as puppet while cleaning up portal:", err)
} }
} else if !puppetsOnly { } else if !puppetsOnly {
_, err = intent.KickUser(portal.MXID, &mautrix.ReqKickUser{UserID: member, Reason: "Deleting portal"}) _, err = intent.KickUser(mxid, &mautrix.ReqKickUser{UserID: member, Reason: "Deleting portal"})
if err != nil { if err != nil {
portal.log.Errorln("Error kicking user while cleaning up portal:", err) log.Errorln("Error kicking user while cleaning up portal:", err)
} }
} }
} }
_, err = intent.LeaveRoom(portal.MXID) _, err = intent.LeaveRoom(mxid)
if err != nil { if err != nil {
portal.log.Errorln("Error leaving with main intent while cleaning up portal:", err) log.Errorln("Error leaving with main intent while cleaning up portal:", err)
} }
} }

58
user.go
View File

@@ -1033,41 +1033,25 @@ func (user *User) bridgeGuild(guildID string, everything bool) error {
} }
func (user *User) unbridgeGuild(guildID string) error { func (user *User) unbridgeGuild(guildID string) error {
//user.guildsLock.Lock() if user.PermissionLevel < bridgeconfig.PermissionLevelAdmin {
//defer user.guildsLock.Unlock() return errors.New("only bridge admins can unbridge guilds")
// }
//guild, exists := user.guilds[guildID] guild := user.bridge.GetGuildByID(guildID, false)
//if !exists { if guild == nil {
// return fmt.Errorf("guildID not found") return errors.New("guild not found")
//} }
// guild.roomCreateLock.Lock()
//if !guild.Bridge { defer guild.roomCreateLock.Unlock()
// return fmt.Errorf("guild not bridged") if !guild.AutoBridgeChannels && guild.MXID == "" {
//} return errors.New("that guild is not bridged")
// }
//// First update the guild so we don't have any other go routines recreating guild.AutoBridgeChannels = false
//// channels we're about to destroy. guild.Update()
//guild.Bridge = false for _, portal := range user.bridge.GetAllPortalsInGuild(guild.ID) {
//guild.Upsert() portal.cleanup(false)
// portal.RemoveMXID()
//// Now run through the channels in the guild and remove any portals we }
//// have for them. guild.cleanup()
//channels, err := user.Session.GuildChannels(guildID) guild.RemoveMXID()
//if err != nil { return nil
// return err
//}
//
//for _, channel := range channels {
// if channelIsBridgeable(channel) {
// key := database.PortalKey{
// ChannelID: channel.ID,
// Receiver: user.DiscordID,
// }
//
// portal := user.bridge.GetPortalByID(key)
// portal.leave(user)
// }
//}
return errors.New("unbridging is not currently supported")
} }