diff --git a/.gitignore b/.gitignore index 7776844..df52687 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ config.yaml discord logs/ -mautrix-discord.db registration.yaml +*.db* diff --git a/discord.go b/discord.go index 05096db..aba2cac 100644 --- a/discord.go +++ b/discord.go @@ -1,16 +1,75 @@ package main import ( + "encoding/json" + "errors" + "github.com/bwmarrin/discordgo" ) -func channelIsBridgeable(channel *discordgo.Channel) bool { +func ptrBool(val bool) *bool { + return &val +} + +func (user *User) channelIsBridgeable(channel *discordgo.Channel) bool { switch channel.Type { - case discordgo.ChannelTypeGuildText: - fallthrough - case discordgo.ChannelTypeGuildNews: - return true + case discordgo.ChannelTypeGuildText, discordgo.ChannelTypeGuildNews: + // allowed + default: + // everything else is not allowed + return false } - return false + hasRole := map[string]bool{ + channel.GuildID: true, + } + var roles []string + member, err := user.Session.State.Member(channel.GuildID, user.DiscordID) + if errors.Is(err, discordgo.ErrStateNotFound) { + user.log.Debugfln("Fetching own membership in %s to check own roles", channel.GuildID) + member, err = user.Session.GuildMember(channel.GuildID, user.DiscordID) + if err != nil { + user.log.Warnfln("Failed to get own membership in %s from server to determine own roles for bridging %s: %v", channel.GuildID, channel.ID, err) + } else { + err = user.Session.State.MemberAdd(member) + if err != nil { + user.log.Warnfln("Failed to add own membership in %s to cache: %v", channel.GuildID, err) + } + } + } else if err != nil { + user.log.Warnfln("Failed to get own membership in %s from cache to determine own roles for bridging %s: %v", channel.GuildID, channel.ID, err) + } + if member != nil { + roles = member.Roles + for _, role := range member.Roles { + hasRole[role] = true + } + } + var userAllowed, roleAllowed *bool + for _, override := range channel.PermissionOverwrites { + if override.Type == discordgo.PermissionOverwriteTypeMember && override.ID == user.DiscordID { + if override.Allow&discordgo.PermissionViewChannel > 0 { + userAllowed = ptrBool(true) + } else if override.Deny&discordgo.PermissionViewChannel > 0 { + userAllowed = ptrBool(false) + } + } else if override.Type == discordgo.PermissionOverwriteTypeRole && hasRole[override.ID] { + if override.Allow&discordgo.PermissionViewChannel > 0 { + roleAllowed = ptrBool(true) + } else if override.Deny&discordgo.PermissionViewChannel > 0 { + roleAllowed = ptrBool(false) + } + } + } + allowed := true + if userAllowed != nil { + allowed = *userAllowed + } else if roleAllowed != nil { + allowed = *roleAllowed + } + if !allowed { + dat, _ := json.Marshal(channel.PermissionOverwrites) + user.log.Debugfln("Permission overwrites (%s) resulted in %s/%s not being allowed to bridge with roles %+v", dat, channel.GuildID, channel.ID, roles) + } + return allowed } diff --git a/user.go b/user.go index f500abd..6c6d90d 100644 --- a/user.go +++ b/user.go @@ -686,7 +686,7 @@ func (user *User) handleGuild(meta *discordgo.Guild, timestamp time.Time, isInSp if len(meta.Channels) > 0 { for _, ch := range meta.Channels { portal := user.GetPortalByMeta(ch) - if (guild.AutoBridgeChannels && channelIsBridgeable(ch)) && portal.MXID == "" { + if guild.AutoBridgeChannels && portal.MXID == "" && user.channelIsBridgeable(ch) { err := portal.CreateMatrixRoom(user, ch) if err != nil { user.log.Errorfln("Failed to create portal for guild channel %s/%s in initial sync: %v", guild.ID, ch.ID, err) @@ -744,11 +744,13 @@ func (user *User) channelCreateHandler(_ *discordgo.Session, c *discordgo.Channe } if c.GuildID == "" { user.handlePrivateChannel(portal, c.Channel, time.Now(), true, user.IsInSpace(portal.Key.String())) - } else { + } else if user.channelIsBridgeable(c.Channel) { err := portal.CreateMatrixRoom(user, c.Channel) if err != nil { user.log.Errorfln("Error creating Matrix room for %s on channel create event: %v", c.ID, err) } + } else { + user.log.Debugfln("Got channel create event for %s, but it's not bridgeable, ignoring", c.ID) } } @@ -1019,7 +1021,7 @@ func (user *User) bridgeGuild(guildID string, everything bool) error { user.addGuildToSpace(guild, false, time.Now()) for _, ch := range meta.Channels { portal := user.GetPortalByMeta(ch) - if (everything && channelIsBridgeable(ch)) || ch.Type == discordgo.ChannelTypeGuildCategory { + if (everything && user.channelIsBridgeable(ch)) || ch.Type == discordgo.ChannelTypeGuildCategory { err = portal.CreateMatrixRoom(user, ch) if err != nil { user.log.Warnfln("Error creating room for guild channel %s: %v", ch.ID, err)