Procházet zdrojové kódy

Automatically unbridge guild when leaving if it has no other Matrix users

Tulir Asokan před 2 roky
rodič
revize
7d959c92dc
5 změnil soubory, kde provedl 23 přidání a 3 odebrání
  1. 1 0
      config/bridge.go
  2. 1 0
      config/upgrade.go
  3. 10 0
      database/userportal.go
  4. 3 0
      example-config.yaml
  5. 8 3
      user.go

+ 1 - 0
config/bridge.go

@@ -46,6 +46,7 @@ type BridgeConfig struct {
 	SyncDirectChatList          bool `yaml:"sync_direct_chat_list"`
 	SyncDirectChatList          bool `yaml:"sync_direct_chat_list"`
 	ResendBridgeInfo            bool `yaml:"resend_bridge_info"`
 	ResendBridgeInfo            bool `yaml:"resend_bridge_info"`
 	DeletePortalOnChannelDelete bool `yaml:"delete_portal_on_channel_delete"`
 	DeletePortalOnChannelDelete bool `yaml:"delete_portal_on_channel_delete"`
+	DeleteGuildOnLeave          bool `yaml:"delete_guild_on_leave"`
 	FederateRooms               bool `yaml:"federate_rooms"`
 	FederateRooms               bool `yaml:"federate_rooms"`
 
 
 	DoublePuppetServerMap      map[string]string `yaml:"double_puppet_server_map"`
 	DoublePuppetServerMap      map[string]string `yaml:"double_puppet_server_map"`

+ 1 - 0
config/upgrade.go

@@ -41,6 +41,7 @@ func DoUpgrade(helper *up.Helper) {
 	helper.Copy(up.Bool, "bridge", "sync_direct_chat_list")
 	helper.Copy(up.Bool, "bridge", "sync_direct_chat_list")
 	helper.Copy(up.Bool, "bridge", "resend_bridge_info")
 	helper.Copy(up.Bool, "bridge", "resend_bridge_info")
 	helper.Copy(up.Bool, "bridge", "delete_portal_on_channel_delete")
 	helper.Copy(up.Bool, "bridge", "delete_portal_on_channel_delete")
+	helper.Copy(up.Bool, "bridge", "delete_guild_on_leave")
 	helper.Copy(up.Bool, "bridge", "federate_rooms")
 	helper.Copy(up.Bool, "bridge", "federate_rooms")
 	helper.Copy(up.Map, "bridge", "double_puppet_server_map")
 	helper.Copy(up.Map, "bridge", "double_puppet_server_map")
 	helper.Copy(up.Bool, "bridge", "double_puppet_allow_discovery")
 	helper.Copy(up.Bool, "bridge", "double_puppet_allow_discovery")

+ 10 - 0
database/userportal.go

@@ -96,6 +96,16 @@ func (u *User) MarkNotInPortal(discordID string) {
 	}
 	}
 }
 }
 
 
+func (u *User) PortalHasOtherUsers(discordID string) (hasOtherUsers bool) {
+	query := `SELECT COUNT(*) > 0 FROM user_portal WHERE user_mxid<>$1 AND discord_id=$2`
+	err := u.db.QueryRow(query, u.MXID, discordID).Scan(&hasOtherUsers)
+	if err != nil {
+		u.log.Errorfln("Failed to check if %s has users other than %s: %v", discordID, u.MXID, err)
+		panic(err)
+	}
+	return
+}
+
 func (u *User) PrunePortalList(beforeTS time.Time) []UserPortal {
 func (u *User) PrunePortalList(beforeTS time.Time) []UserPortal {
 	query := `
 	query := `
 		DELETE FROM user_portal
 		DELETE FROM user_portal

+ 3 - 0
example-config.yaml

@@ -128,6 +128,9 @@ bridge:
     # Should the bridge attempt to completely delete portal rooms when a channel is deleted on Discord?
     # Should the bridge attempt to completely delete portal rooms when a channel is deleted on Discord?
     # If true, the bridge will try to kick Matrix users from the room. Otherwise, the bridge only makes ghosts leave.
     # If true, the bridge will try to kick Matrix users from the room. Otherwise, the bridge only makes ghosts leave.
     delete_portal_on_channel_delete: false
     delete_portal_on_channel_delete: false
+    # Should the bridge delete all portal rooms when you leave a guild on Discord?
+    # This only applies if the guild has no other Matrix users on this bridge instance.
+    delete_guild_on_leave: true
     # Whether or not created rooms should have federation enabled.
     # Whether or not created rooms should have federation enabled.
     # If false, created portal rooms will never be federated.
     # If false, created portal rooms will never be federated.
     federate_rooms: true
     federate_rooms: true

+ 8 - 3
user.go

@@ -780,7 +780,12 @@ func (user *User) guildDeleteHandler(_ *discordgo.Session, g *discordgo.GuildDel
 	if guild == nil || guild.MXID == "" {
 	if guild == nil || guild.MXID == "" {
 		return
 		return
 	}
 	}
-	// TODO clean up?
+	if user.bridge.Config.Bridge.DeleteGuildOnLeave && !user.PortalHasOtherUsers(g.ID) {
+		err := user.unbridgeGuild(g.ID)
+		if err != nil {
+			user.log.Warnfln("Failed to unbridge guild that was deleted: %v", err)
+		}
+	}
 }
 }
 
 
 func (user *User) guildUpdateHandler(_ *discordgo.Session, g *discordgo.GuildUpdate) {
 func (user *User) guildUpdateHandler(_ *discordgo.Session, g *discordgo.GuildUpdate) {
@@ -1086,8 +1091,8 @@ func (user *User) bridgeGuild(guildID string, everything bool) error {
 }
 }
 
 
 func (user *User) unbridgeGuild(guildID string) error {
 func (user *User) unbridgeGuild(guildID string) error {
-	if user.PermissionLevel < bridgeconfig.PermissionLevelAdmin {
-		return errors.New("only bridge admins can unbridge guilds")
+	if user.PermissionLevel < bridgeconfig.PermissionLevelAdmin && user.PortalHasOtherUsers(guildID) {
+		return errors.New("only bridge admins can unbridge guilds with other users")
 	}
 	}
 	guild := user.bridge.GetGuildByID(guildID, false)
 	guild := user.bridge.GetGuildByID(guildID, false)
 	if guild == nil {
 	if guild == nil {