diff --git a/config/bridge.go b/config/bridge.go index 8e00da1..6e1fa5a 100644 --- a/config/bridge.go +++ b/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 { diff --git a/config/upgrade.go b/config/upgrade.go index 42c312d..8338105 100644 --- a/config/upgrade.go +++ b/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") diff --git a/database/message.go b/database/message.go index 51ebb46..d051394 100644 --- a/database/message.go +++ b/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" diff --git a/example-config.yaml b/example-config.yaml index bced601..4a698b5 100644 --- a/example-config.yaml +++ b/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 diff --git a/portal.go b/portal.go index d4d0d79..518e76c 100644 --- a/portal.go +++ b/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,11 +1216,23 @@ 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) { if portal.MXID == "" { return diff --git a/user.go b/user.go index 8d1833c..46ddece 100644 --- a/user.go +++ b/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) {