Skip to content

Commit

Permalink
reminders: verify that member can run remindme in target channel (#…
Browse files Browse the repository at this point in the history
…1674)

* commands: move code handling cmd overrides for threads into YagCommand.GetSettings

Previously this logic was done by the caller, but it should be the responsibility of the GetSettings procedure. This commit also incidentally fixes a minor bug in CommonContainerNotFoundHandler, which previously did not consider command overrides properly if used in a thread.

* reminders: verify that member can run `remindme` in target channel
  • Loading branch information
jo3-l authored Jun 21, 2024
1 parent 2986f57 commit b213ce5
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 25 deletions.
3 changes: 1 addition & 2 deletions commands/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,9 @@ func CommonContainerNotFoundHandler(container *dcmd.Container, fixedMessage stri
return func(data *dcmd.Data) (interface{}, error) {
// Only show stuff if atleast 1 of the commands in the container is enabled
if data.GuildData != nil {
cParentID := data.GuildData.CS.ParentID
ms := data.GuildData.MS

channelOverrides, err := GetOverridesForChannel(data.ChannelID, cParentID, data.GuildData.GS.ID)
channelOverrides, err := GetOverridesForChannel(data.GuildData.CS, data.GuildData.GS)
if err != nil {
logger.WithError(err).WithField("guild", data.GuildData.GS.ID).Error("failed retrieving command overrides")
return nil, nil
Expand Down
37 changes: 17 additions & 20 deletions commands/yagcommmand.go
Original file line number Diff line number Diff line change
Expand Up @@ -437,16 +437,8 @@ func (yc *YAGCommand) checkCanExecuteCommand(data *dcmd.Data) (canExecute bool,
return false, nil, nil, nil
}
}
channel_id := data.GuildData.CS.ID
parent_id := data.GuildData.CS.ParentID
// in case the channel is a thread, get the parent channel from parent id and check for the overrides
if data.GuildData.CS.Type.IsThread() {
channel := data.GuildData.GS.GetChannel(parent_id)
channel_id = channel.ID
parent_id = channel.ParentID
}

settings, err = yc.GetSettings(data.ContainerChain, channel_id, parent_id, guild.ID)
settings, err = yc.GetSettings(data.ContainerChain, data.GuildData.CS, guild)
if err != nil {
resp = &CanExecuteError{
Type: ReasonError,
Expand Down Expand Up @@ -721,9 +713,14 @@ type CommandSettings struct {
IgnoreRoles []int64
}

func GetOverridesForChannel(channelID, channelParentID, guildID int64) ([]*models.CommandsChannelsOverride, error) {
func GetOverridesForChannel(cs *dstate.ChannelState, guild *dstate.GuildSet) ([]*models.CommandsChannelsOverride, error) {
if cs.Type.IsThread() {
// Look for overrides from the parent channel, not the thread.
cs = guild.GetChannel(cs.ParentID)
}

// Fetch the overrides from the database, we treat the global settings as an override for simplicity
channelOverrides, err := models.CommandsChannelsOverrides(qm.Where("(? = ANY (channels) OR global=true OR ? = ANY (channel_categories)) AND guild_id=?", channelID, channelParentID, guildID), qm.Load("CommandsCommandOverrides")).AllG(context.Background())
channelOverrides, err := models.CommandsChannelsOverrides(qm.Where("(? = ANY (channels) OR global=true OR ? = ANY (channel_categories)) AND guild_id=?", cs.ID, cs.ParentID, guild.ID), qm.Load("CommandsCommandOverrides")).AllG(context.Background())
if err != nil {
return nil, err
}
Expand All @@ -732,23 +729,23 @@ func GetOverridesForChannel(channelID, channelParentID, guildID int64) ([]*model
}

// GetSettings returns the settings from the command, generated from the servers channel and command overrides
func (cs *YAGCommand) GetSettings(containerChain []*dcmd.Container, channelID, channelParentID, guildID int64) (settings *CommandSettings, err error) {
func (yc *YAGCommand) GetSettings(containerChain []*dcmd.Container, cs *dstate.ChannelState, guild *dstate.GuildSet) (settings *CommandSettings, err error) {

// Fetch the overrides from the database, we treat the global settings as an override for simplicity
channelOverrides, err := GetOverridesForChannel(channelID, channelParentID, guildID)
channelOverrides, err := GetOverridesForChannel(cs, guild)
if err != nil {
err = errors.WithMessage(err, "GetOverridesForChannel")
return
}

return cs.GetSettingsWithLoadedOverrides(containerChain, guildID, channelOverrides)
return yc.GetSettingsWithLoadedOverrides(containerChain, guild.ID, channelOverrides)
}

func (cs *YAGCommand) GetSettingsWithLoadedOverrides(containerChain []*dcmd.Container, guildID int64, channelOverrides []*models.CommandsChannelsOverride) (settings *CommandSettings, err error) {
func (yc *YAGCommand) GetSettingsWithLoadedOverrides(containerChain []*dcmd.Container, guildID int64, channelOverrides []*models.CommandsChannelsOverride) (settings *CommandSettings, err error) {
settings = &CommandSettings{}

// Some commands have custom places to toggle their enabled status
ce, err := cs.customEnabled(guildID)
ce, err := yc.customEnabled(guildID)
if err != nil {
err = errors.WithMessage(err, "customEnabled")
return
Expand All @@ -758,7 +755,7 @@ func (cs *YAGCommand) GetSettingsWithLoadedOverrides(containerChain []*dcmd.Cont
return
}

if cs.HideFromCommandsPage {
if yc.HideFromCommandsPage {
settings.Enabled = true
return
}
Expand All @@ -780,20 +777,20 @@ func (cs *YAGCommand) GetSettingsWithLoadedOverrides(containerChain []*dcmd.Cont
}
}

cmdFullName := cs.Name
cmdFullName := yc.Name
if len(containerChain) > 1 {
lastContainer := containerChain[len(containerChain)-1]
cmdFullName = lastContainer.Names[0] + " " + cmdFullName
}

// Assign the global settings, if existing
if global != nil {
cs.fillSettings(cmdFullName, global, settings)
yc.fillSettings(cmdFullName, global, settings)
}

// Assign the channel override, if existing
if channelOverride != nil {
cs.fillSettings(cmdFullName, channelOverride, settings)
yc.fillSettings(cmdFullName, channelOverride, settings)
}

return
Expand Down
37 changes: 34 additions & 3 deletions reminders/plugin_bot.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,37 @@ var cmds = []*commands.YAGCommand{

id := parsed.ChannelID
if c := parsed.Switch("channel"); c.Value != nil {
id = c.Value.(*dstate.ChannelState).ID
cs := c.Value.(*dstate.ChannelState)
mention, _ := cs.Mention()

hasPerms, err := bot.AdminOrPermMS(parsed.GuildData.GS.ID, id, parsed.GuildData.MS, discordgo.PermissionSendMessages|discordgo.PermissionViewChannel)
hasPerms, err := bot.AdminOrPermMS(parsed.GuildData.GS.ID, cs.ID, parsed.GuildData.MS, discordgo.PermissionSendMessages|discordgo.PermissionViewChannel)
if err != nil {
return "Failed checking permissions; please try again or join the support server.", err
}

if !hasPerms {
return "You do not have permissions to send messages there", nil
return fmt.Sprintf("You do not have permissions to send messages in %s", mention), nil
}

// Ensure the member can run the `remindme` command in the
// target channel according to the configured command and
// channel overrides, if any.
yc := parsed.Cmd.Command.(*commands.YAGCommand)
settings, err := yc.GetSettings(parsed.ContainerChain, cs, parsed.GuildData.GS)
if err != nil {
return "Failed fetching command settings", err
}

if !settings.Enabled {
return fmt.Sprintf("The `remindme` command is disabled in %s", mention), nil
}

ms := parsed.GuildData.MS
// If there are no required roles set, the member should be allowed to run the command.
hasRequiredRoles := len(settings.RequiredRoles) == 0 || memberHasAnyRole(ms, settings.RequiredRoles)
hasIgnoredRoles := memberHasAnyRole(ms, settings.IgnoreRoles)
if !hasRequiredRoles || hasIgnoredRoles {
return fmt.Sprintf("You cannot use the `remindme` command in %s", mention), nil
}
}

Expand Down Expand Up @@ -230,6 +252,15 @@ var cmds = []*commands.YAGCommand{
},
}

func memberHasAnyRole(ms *dstate.MemberState, roles []int64) bool {
for _, r := range ms.Member.Roles {
if common.ContainsInt64Slice(roles, r) {
return true
}
}
return false
}

func checkUserScheduledEvent(evt *seventsmodels.ScheduledEvent, data interface{}) (retry bool, err error) {
// IMPORTANT: evt.GuildID can be 1 in cases where it was migrated from the
// legacy scheduled event system.
Expand Down

0 comments on commit b213ce5

Please sign in to comment.