ソースを参照

Bridge channel deletions from Discord

Tulir Asokan 3 年 前
コミット
7f0f77423d
6 ファイル変更60 行追加30 行削除
  1. 17 19
      config/bridge.go
  2. 1 0
      config/upgrade.go
  3. 9 0
      database/message.go
  4. 3 0
      example-config.yaml
  5. 21 10
      portal.go
  6. 9 1
      user.go

+ 17 - 19
config/bridge.go

@@ -28,33 +28,31 @@ import (
 )
 
 type BridgeConfig struct {
-	UsernameTemplate      string `yaml:"username_template"`
-	DisplaynameTemplate   string `yaml:"displayname_template"`
-	ChannelNameTemplate   string `yaml:"channel_name_template"`
-	GuildNameTemplate     string `yaml:"guild_name_template"`
-	PrivateChatPortalMeta bool   `yaml:"private_chat_portal_meta"`
-
-	PrivateChannelCreateLimit int `yaml:"startup_private_channel_create_limit"`
-
-	DeliveryReceipts    bool `yaml:"delivery_receipts"`
-	MessageStatusEvents bool `yaml:"message_status_events"`
-	MessageErrorNotices bool `yaml:"message_error_notices"`
-	RestrictedRooms     bool `yaml:"restricted_rooms"`
-
-	CommandPrefix string `yaml:"command_prefix"`
-
-	ManagementRoomText bridgeconfig.ManagementRoomTexts `yaml:"management_room_text"`
+	UsernameTemplate          string `yaml:"username_template"`
+	DisplaynameTemplate       string `yaml:"displayname_template"`
+	ChannelNameTemplate       string `yaml:"channel_name_template"`
+	GuildNameTemplate         string `yaml:"guild_name_template"`
+	PrivateChatPortalMeta     bool   `yaml:"private_chat_portal_meta"`
+	PrivateChannelCreateLimit int    `yaml:"startup_private_channel_create_limit"`
 
 	PortalMessageBuffer int `yaml:"portal_message_buffer"`
 
-	SyncDirectChatList bool `yaml:"sync_direct_chat_list"`
-	ResendBridgeInfo   bool `yaml:"resend_bridge_info"`
-	FederateRooms      bool `yaml:"federate_rooms"`
+	DeliveryReceipts            bool `yaml:"delivery_receipts"`
+	MessageStatusEvents         bool `yaml:"message_status_events"`
+	MessageErrorNotices         bool `yaml:"message_error_notices"`
+	RestrictedRooms             bool `yaml:"restricted_rooms"`
+	SyncDirectChatList          bool `yaml:"sync_direct_chat_list"`
+	ResendBridgeInfo            bool `yaml:"resend_bridge_info"`
+	DeletePortalOnChannelDelete bool `yaml:"delete_portal_on_channel_delete"`
+	FederateRooms               bool `yaml:"federate_rooms"`
 
 	DoublePuppetServerMap      map[string]string `yaml:"double_puppet_server_map"`
 	DoublePuppetAllowDiscovery bool              `yaml:"double_puppet_allow_discovery"`
 	LoginSharedSecretMap       map[string]string `yaml:"login_shared_secret_map"`
 
+	CommandPrefix      string                           `yaml:"command_prefix"`
+	ManagementRoomText bridgeconfig.ManagementRoomTexts `yaml:"management_room_text"`
+
 	Encryption bridgeconfig.EncryptionConfig `yaml:"encryption"`
 
 	Provisioning struct {

+ 1 - 0
config/upgrade.go

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

+ 9 - 0
database/message.go

@@ -71,6 +71,15 @@ func (mq *MessageQuery) GetLastInThread(key PortalKey, threadID string) *Message
 	return mq.New().Scan(mq.db.QueryRow(query, key.ChannelID, key.Receiver, threadID))
 }
 
+func (mq *MessageQuery) DeleteAll(key PortalKey) {
+	query := "DELETE FROM message WHERE dc_chan_id=$1 AND dc_chan_receiver=$2"
+	_, err := mq.db.Exec(query, key.ChannelID, key.Receiver)
+	if err != nil {
+		mq.log.Warnfln("Failed to delete messages of %s: %v", key, err)
+		panic(err)
+	}
+}
+
 func (mq *MessageQuery) GetByMXID(key PortalKey, mxid id.EventID) *Message {
 	query := messageSelect + " WHERE dc_chan_id=$1 AND dc_chan_receiver=$2 AND mxid=$3"
 

+ 3 - 0
example-config.yaml

@@ -112,6 +112,9 @@ bridge:
     # Set this to true to tell the bridge to re-send m.bridge events to all rooms on the next run.
     # This field will automatically be changed back to false after it, except if the config file is not writable.
     resend_bridge_info: false
+    # 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.
+    delete_portal_on_channel_delete: false
     # Whether or not created rooms should have federation enabled.
     # If false, created portal rooms will never be federated.
     federate_rooms: true

+ 21 - 10
portal.go

@@ -1174,13 +1174,14 @@ func (portal *Portal) sendDeliveryReceipt(eventID id.EventID) {
 }
 
 func (portal *Portal) HandleMatrixLeave(brSender bridge.User) {
-	portal.log.Debugln("User left private chat portal, cleaning up and deleting...")
-	portal.Delete()
-	portal.cleanup(false)
-
-	// TODO: figure out how to close a dm from the API.
-
-	portal.cleanupIfEmpty()
+	sender := brSender.(*User)
+	if portal.IsPrivateChat() && sender.DiscordID == portal.Key.Receiver {
+		portal.log.Debugln("User left private chat portal, cleaning up and deleting...")
+		portal.Delete()
+		portal.cleanup(false)
+	} else {
+		portal.cleanupIfEmpty()
+	}
 }
 
 func (portal *Portal) leave(sender *User) {
@@ -1196,11 +1197,9 @@ func (portal *Portal) Delete() {
 	portal.Portal.Delete()
 	portal.bridge.portalsLock.Lock()
 	delete(portal.bridge.portalsByID, portal.Key)
-
 	if portal.MXID != "" {
 		delete(portal.bridge.portalsByMXID, portal.MXID)
 	}
-
 	portal.bridge.portalsLock.Unlock()
 }
 
@@ -1217,9 +1216,21 @@ func (portal *Portal) cleanupIfEmpty() {
 
 	if len(users) == 0 {
 		portal.log.Infoln("Room seems to be empty, cleaning up...")
-		portal.Delete()
 		portal.cleanup(false)
+		portal.RemoveMXID()
+	}
+}
+
+func (portal *Portal) RemoveMXID() {
+	portal.bridge.portalsLock.Lock()
+	defer portal.bridge.portalsLock.Unlock()
+	if portal.MXID == "" {
+		return
 	}
+	delete(portal.bridge.portalsByMXID, portal.MXID)
+	portal.MXID = ""
+	portal.Update()
+	portal.bridge.DB.Message.DeleteAll(portal.Key)
 }
 
 func (portal *Portal) cleanup(puppetsOnly bool) {

+ 9 - 1
user.go

@@ -750,7 +750,15 @@ func (user *User) channelCreateHandler(_ *discordgo.Session, c *discordgo.Channe
 }
 
 func (user *User) channelDeleteHandler(_ *discordgo.Session, c *discordgo.ChannelDelete) {
-	user.log.Debugln("channel delete handler")
+	portal := user.GetExistingPortalByID(c.ID)
+	if portal == nil {
+		user.log.Debugfln("Ignoring delete of unknown channel %s/%s", c.GuildID, c.ID)
+		return
+	}
+	user.log.Infofln("Got delete notification for %s/%s, cleaning up portal", c.GuildID, c.ID)
+	portal.Delete()
+	portal.cleanup(!user.bridge.Config.Bridge.DeletePortalOnChannelDelete)
+	user.log.Debugfln("Completed cleaning up %s/%s", c.GuildID, c.ID)
 }
 
 func (user *User) channelPinsUpdateHandler(_ *discordgo.Session, c *discordgo.ChannelPinsUpdate) {