Documentation ¶
Index ¶
- Constants
- Variables
- func AddMemberMuteRole(config *Config, id int64, currentRoles []int64) (removedRoles []int64, err error)
- func AdvancedDeleteMessages(channelID int64, filterUser int64, regex string, toID int64, ...) (int, error)
- func BanUser(config *Config, guildID int64, channel *dstate.ChannelState, ...) error
- func BanUserWithDuration(config *Config, guildID int64, channel *dstate.ChannelState, ...) error
- func CreateDeleteLogEmbed(config *Config, author *discordgo.User, target *discordgo.User, ...) error
- func CreateLogs(guildID, channelID int64, user *discordgo.User) string
- func CreateModlogEmbed(config *Config, author *discordgo.User, action ModlogAction, ...) error
- func CreateUpdateLogEmbed(config *Config, author *discordgo.User, ...) error
- func DeleteMessages(channelID int64, filterUser int64, deleteNum, fetchNum int) (int, error)
- func FindAuditLogEntry(guildID int64, typ int, targetUser int64, within time.Duration) (author *discordgo.User, entry *discordgo.AuditLogEntry)
- func FindAuditLogEntryByChannel(guildID int64, typ int, targetChannel int64, within time.Duration) (author *discordgo.User, entry *discordgo.AuditLogEntry)
- func FindRole(gs *dstate.GuildState, roleS string) *discordgo.Role
- func GenericCmdResp(action ModlogAction, target *discordgo.User, duration time.Duration, ...) string
- func GetMessage(ChannelID int64, ID int64) (message *dstate.MessageState)
- func HandleChannelCreateUpdate(evt *eventsystem.EventData) (retry bool, err error)
- func HandleClearServerWarnings(w http.ResponseWriter, r *http.Request) (web.TemplateData, error)
- func HandleGuildBanAddRemove(evt *eventsystem.EventData)
- func HandleGuildCreate(evt *eventsystem.EventData)
- func HandleGuildMemberRemove(evt *eventsystem.EventData) (retry bool, err error)
- func HandleGuildMemberUpdate(evt *eventsystem.EventData) (retry bool, err error)
- func HandleMemberJoin(evt *eventsystem.EventData) (retry bool, err error)
- func HandleMemberJoinLog(evt *eventsystem.EventData) (retry bool, err error)
- func HandleMessageRemove(evt *eventsystem.EventData) (retry bool, err error)
- func HandleMessageUpdate(evt *eventsystem.EventData) (retry bool, err error)
- func HandleModeration(w http.ResponseWriter, r *http.Request) (web.TemplateData, error)
- func HandlePostModeration(w http.ResponseWriter, r *http.Request) (web.TemplateData, error)
- func HandleRefreshMuteOverrides(evt *pubsub.Event)
- func KickUser(config *Config, guildID int64, channel *dstate.ChannelState, ...) error
- func LockMemberMuteMW(next eventsystem.HandlerFunc) eventsystem.HandlerFunc
- func LockMute(uID int64)
- func MBaseCmdSecond(cmdData *dcmd.Data, reason string, reasonArgOptional bool, neededPerm int, ...) (oreason string, err error)
- func MuteUnmuteUser(config *Config, mute bool, guildID int64, channel *dstate.ChannelState, ...) error
- func PaginateWarnings(parsed *dcmd.Data) ...
- func RedisKeyBannedUser(guildID, userID int64) string
- func RedisKeyLockedMute(guildID, userID int64) string
- func RedisKeyMutedUser(guildID, userID int64) string
- func RedisKeyUnbannedUser(guildID, userID int64) string
- func RefreshMuteOverrideForChannel(config *Config, channel *discordgo.Channel)
- func RefreshMuteOverrides(guildID int64)
- func RegisterPlugin()
- func RemoveMemberMuteRole(config *Config, id int64, currentRoles []int64, mute MuteModel) (err error)
- func SafeArgString(data *dcmd.Data, arg int) string
- func SlowModeFunc(config *Config, guildID int64, channel *dstate.ChannelState, ...) (interface{}, error)
- func UnbanUser(config *Config, guildID int64, author *discordgo.User, reason string, ...) (bool, error)
- func UnlockMute(uID int64)
- func WarnUser(config *Config, guildID int64, channel *dstate.ChannelState, ...) error
- type ChannelRatelimitData
- type Config
- type ContextKey
- type ModPlugin
- type ModlogAction
- type MuteModel
- type Plugin
- func (p *Plugin) AddCommands()
- func (p *Plugin) AllFeatureFlags() []string
- func (p *Plugin) BotInit()
- func (p *Plugin) InitWeb()
- func (p *Plugin) LoadServerHomeWidget(w http.ResponseWriter, r *http.Request) (web.TemplateData, error)
- func (p *Plugin) PluginInfo() *common.PluginInfo
- func (p *Plugin) ShardMigrationReceive(evt dshardorchestrator.EventType, data interface{})
- func (p *Plugin) UpdateFeatureFlags(guildID int64) ([]string, error)
- type Punishment
- type ScheduledUnbanData
- type ScheduledUnmuteData
- type WarnRankEntry
- type WarningModel
Constants ¶
View Source
const ( ActionMuted = "Muted" ActionUnMuted = "Unmuted" ActionKicked = "Kicked" ActionBanned = "Banned" ActionUnbanned = "Unbanned" ActionWarned = "Warned" )
View Source
const (
DefaultDMMessage = `You have been {{.ModAction}}
{{if .Reason}}**Reason:** {{.Reason}}{{end}}`
)
View Source
const (
ErrNoMuteRole = errors.Sentinel("No mute role")
)
View Source
const MuteDeniedChannelPerms = discordgo.PermissionSendMessages | discordgo.PermissionVoiceSpeak
Variables ¶
View Source
var ( MAMute = ModlogAction{Prefix: "Muted", Emoji: "🔇", Color: 0x57728e} MAUnmute = ModlogAction{Prefix: "Unmuted", Emoji: "🔊", Color: 0x62c65f} MAKick = ModlogAction{Prefix: "Kicked", Emoji: "👢", Color: 0xf2a013} MABanned = ModlogAction{Prefix: "Banned", Emoji: "🔨", Color: 0xd64848} MAUnbanned = ModlogAction{Prefix: "Unbanned", Emoji: "🔓", Color: 0x62c65f} MAWarned = ModlogAction{Prefix: "Warned", Emoji: "⚠", Color: 0xfca253} MASlowmode = ModlogAction{Prefix: "Slowed", Emoji: "🐌", Color: 0xff9a00} MARemoveSlow = ModlogAction{Prefix: "Removed slowmode", Emoji: "💨", Color: 0x43ff00} MAGiveRole = ModlogAction{Prefix: "", Emoji: "➕", Color: 0x53fcf9} MARemoveRole = ModlogAction{Prefix: "", Emoji: "➖", Color: 0x53fcf9} MALeave = ModlogAction{Prefix: "Left", Emoji: "➖", Color: 0xd64848} MAJoin = ModlogAction{Prefix: "Joined", Emoji: "➕", Color: 0x62c65f} )
View Source
var (
ErrFailedPerms = errors.New("Failed retrieving perms")
)
View Source
var ModerationCommands = []*commands.YAGCommand{ &commands.YAGCommand{ CustomEnabled: true, CmdCategory: commands.CategoryModeration, Name: "Ban", Aliases: []string{"banid"}, Description: "Bans a member, specify a duration with -d and specify number of days of messages to delete with -ddays (0 to 7)", RequiredArgs: 1, Arguments: []*dcmd.ArgDef{ &dcmd.ArgDef{Name: "User", Type: dcmd.UserID}, &dcmd.ArgDef{Name: "Reason", Type: dcmd.String}, }, ArgSwitches: []*dcmd.ArgDef{ &dcmd.ArgDef{Switch: "d", Default: time.Duration(0), Name: "Duration", Type: &commands.DurationArg{}}, &dcmd.ArgDef{Switch: "ddays", Name: "Days", Type: dcmd.Int}, }, RunFunc: func(parsed *dcmd.Data) (interface{}, error) { config, target, err := MBaseCmd(parsed, parsed.Args[0].Int64()) if err != nil { return nil, err } reason := SafeArgString(parsed, 1) reason, err = MBaseCmdSecond(parsed, reason, config.BanReasonOptional, discordgo.PermissionBanMembers, config.BanCmdRoles, config.BanEnabled) if err != nil { return nil, err } ddays := int(config.DefaultBanDeleteDays.Int64) if parsed.Switches["ddays"].Value != nil { ddays = parsed.Switches["ddays"].Int() } err = BanUserWithDuration(config, parsed.GS.ID, parsed.CS, parsed.Msg, parsed.Msg.Author, reason, target, parsed.Switches["d"].Value.(time.Duration), ddays) if err != nil { return nil, err } return GenericCmdResp(MABanned, target, parsed.Switch("d").Value.(time.Duration), true, false), nil }, }, &commands.YAGCommand{ CustomEnabled: true, CmdCategory: commands.CategoryModeration, Name: "Unban", Aliases: []string{"unbanid"}, Description: "Unbans a user. Reason requirement is same as ban command setting.", RequiredArgs: 1, Arguments: []*dcmd.ArgDef{ &dcmd.ArgDef{Name: "User", Type: dcmd.UserID}, &dcmd.ArgDef{Name: "Reason", Type: dcmd.String}, }, RunFunc: func(parsed *dcmd.Data) (interface{}, error) { config, _, err := MBaseCmd(parsed, 0) if err != nil { return nil, err } reason := SafeArgString(parsed, 1) reason, err = MBaseCmdSecond(parsed, reason, config.BanReasonOptional, discordgo.PermissionBanMembers, config.BanCmdRoles, config.BanEnabled) if err != nil { return nil, err } targetID := parsed.Args[0].Int64() target := &discordgo.User{ Username: "unknown", Discriminator: "????", ID: targetID, } targetMem := parsed.GS.MemberCopy(true, targetID) if targetMem != nil { return "User is not banned!", nil } isNotBanned, err := UnbanUser(config, parsed.GS.ID, parsed.Msg.Author, reason, target) if err != nil { return nil, err } if isNotBanned { return "User is not banned!", nil } return GenericCmdResp(MAUnbanned, target, 0, true, true), nil }, }, &commands.YAGCommand{ CustomEnabled: true, CmdCategory: commands.CategoryModeration, Name: "Kick", Description: "Kicks a member", RequiredArgs: 1, Arguments: []*dcmd.ArgDef{ &dcmd.ArgDef{Name: "User", Type: dcmd.UserID}, &dcmd.ArgDef{Name: "Reason", Type: dcmd.String}, }, RunFunc: func(parsed *dcmd.Data) (interface{}, error) { config, target, err := MBaseCmd(parsed, parsed.Args[0].Int64()) if err != nil { return nil, err } reason := SafeArgString(parsed, 1) reason, err = MBaseCmdSecond(parsed, reason, config.KickReasonOptional, discordgo.PermissionKickMembers, config.KickCmdRoles, config.KickEnabled) if err != nil { return nil, err } err = KickUser(config, parsed.GS.ID, parsed.CS, parsed.Msg, parsed.Msg.Author, reason, target) if err != nil { return nil, err } return GenericCmdResp(MAKick, target, 0, true, true), nil }, }, &commands.YAGCommand{ CustomEnabled: true, CmdCategory: commands.CategoryModeration, Name: "Mute", Description: "Mutes a member", Arguments: []*dcmd.ArgDef{ &dcmd.ArgDef{Name: "User", Type: dcmd.UserID}, &dcmd.ArgDef{Name: "Duration", Type: &commands.DurationArg{}}, &dcmd.ArgDef{Name: "Reason", Type: dcmd.String}, }, ArgumentCombos: [][]int{[]int{0, 1, 2}, []int{0, 2, 1}, []int{0, 1}, []int{0, 2}, []int{0}}, RunFunc: func(parsed *dcmd.Data) (interface{}, error) { config, target, err := MBaseCmd(parsed, parsed.Args[0].Int64()) if err != nil { return nil, err } if config.MuteRole == "" { return "No mute role set up, assign a mute role in the control panel", nil } reason := parsed.Args[2].Str() reason, err = MBaseCmdSecond(parsed, reason, config.MuteReasonOptional, discordgo.PermissionKickMembers, config.MuteCmdRoles, config.MuteEnabled) if err != nil { return nil, err } d := time.Duration(config.DefaultMuteDuration.Int64) * time.Minute if parsed.Args[1].Value != nil { d = parsed.Args[1].Value.(time.Duration) } if d > 0 && d < time.Minute { d = time.Minute } logger.Info(d.Seconds()) member, err := bot.GetMember(parsed.GS.ID, target.ID) if err != nil || member == nil { return "Member not found", err } err = MuteUnmuteUser(config, true, parsed.GS.ID, parsed.CS, parsed.Msg, parsed.Msg.Author, reason, member, int(d.Minutes())) if err != nil { return nil, err } return GenericCmdResp(MAMute, target, d, true, false), nil }, }, &commands.YAGCommand{ CustomEnabled: true, CmdCategory: commands.CategoryModeration, Name: "Unmute", Description: "Unmutes a member", RequiredArgs: 1, Arguments: []*dcmd.ArgDef{ &dcmd.ArgDef{Name: "User", Type: dcmd.UserID}, &dcmd.ArgDef{Name: "Reason", Type: dcmd.String}, }, RunFunc: func(parsed *dcmd.Data) (interface{}, error) { config, target, err := MBaseCmd(parsed, parsed.Args[0].Int64()) if err != nil { return nil, err } if config.MuteRole == "" { return "No mute role set up, assign a mute role in the control panel", nil } reason := parsed.Args[1].Str() reason, err = MBaseCmdSecond(parsed, reason, config.UnmuteReasonOptional, discordgo.PermissionKickMembers, config.MuteCmdRoles, config.MuteEnabled) if err != nil { return nil, err } member, err := bot.GetMember(parsed.GS.ID, target.ID) if err != nil || member == nil { return "Member not found", err } err = MuteUnmuteUser(config, false, parsed.GS.ID, parsed.CS, parsed.Msg, parsed.Msg.Author, reason, member, 0) if err != nil { return nil, err } return GenericCmdResp(MAUnmute, target, 0, false, true), nil }, }, &commands.YAGCommand{ CustomEnabled: true, Cooldown: 5, CmdCategory: commands.CategoryModeration, Name: "Report", Description: "Reports a member to the server's staff", RequiredArgs: 2, Arguments: []*dcmd.ArgDef{ &dcmd.ArgDef{Name: "User", Type: dcmd.UserID}, &dcmd.ArgDef{Name: "Reason", Type: dcmd.String}, }, RunFunc: func(parsed *dcmd.Data) (interface{}, error) { config, _, err := MBaseCmd(parsed, 0) if err != nil { return nil, err } _, err = MBaseCmdSecond(parsed, "", true, 0, nil, config.ReportEnabled) if err != nil { return nil, err } target := parsed.Args[0].Int64() logLink := CreateLogs(parsed.GS.ID, parsed.CS.ID, parsed.Msg.Author) channelID := config.IntReportChannel() if channelID == 0 { return "No report channel set up", nil } reportBody := fmt.Sprintf("<@%d> Reported <@%d> in <#%d> For `%s`\nLast 100 messages from channel: <%s>", parsed.Msg.Author.ID, target, parsed.Msg.ChannelID, parsed.Args[1].Str(), logLink) _, err = common.BotSession.ChannelMessageSendComplex(channelID, &discordgo.MessageSend{ Content: reportBody, AllowedMentions: discordgo.AllowedMentions{ Users: []int64{parsed.Msg.Author.ID, target}, }, }) if err != nil { return nil, err } if channelID != parsed.Msg.ChannelID { return "User reported to the proper authorities", nil } return nil, nil }, }, &commands.YAGCommand{ CustomEnabled: true, CmdCategory: commands.CategoryModeration, Name: "Clean", Description: "Delete the last number of messages from chat, optionally filtering by user, max age and regex or ignoring pinned messages.", LongDescription: "Specify a regex with \"-r regex_here\" and max age with \"-ma 1h10m\"\nNote: Will only look in the last 1k messages", Aliases: []string{"clear", "cl"}, RequiredArgs: 1, Arguments: []*dcmd.ArgDef{ &dcmd.ArgDef{Name: "Num", Type: &dcmd.IntArg{Min: 1, Max: 100}}, &dcmd.ArgDef{Name: "User", Type: dcmd.UserID, Default: 0}, }, ArgSwitches: []*dcmd.ArgDef{ &dcmd.ArgDef{Switch: "r", Name: "Regex", Type: dcmd.String}, &dcmd.ArgDef{Switch: "ma", Default: time.Duration(0), Name: "Max age", Type: &commands.DurationArg{}}, &dcmd.ArgDef{Switch: "minage", Default: time.Duration(0), Name: "Min age", Type: &commands.DurationArg{}}, &dcmd.ArgDef{Switch: "i", Name: "Regex case insensitive"}, &dcmd.ArgDef{Switch: "nopin", Name: "Ignore pinned messages"}, &dcmd.ArgDef{Switch: "a", Name: "Only remove messages with attachments"}, &dcmd.ArgDef{Switch: "to", Name: "Stop at this msg ID", Type: dcmd.Int}, }, ArgumentCombos: [][]int{[]int{0}, []int{0, 1}, []int{1, 0}}, RunFunc: func(parsed *dcmd.Data) (interface{}, error) { config, _, err := MBaseCmd(parsed, 0) if err != nil { return nil, err } _, err = MBaseCmdSecond(parsed, "", true, discordgo.PermissionManageMessages, nil, config.CleanEnabled) if err != nil { return nil, err } userFilter := parsed.Args[1].Int64() num := parsed.Args[0].Int() if (userFilter == 0 || userFilter == parsed.Msg.Author.ID) && parsed.Source != 0 { num++ } if num > 100 { num = 100 } if num < 1 { if num < 0 { return errors.New("Bot is having a stroke <https://www.youtube.com/watch?v=dQw4w9WgXcQ>"), nil } return errors.New("Can't delete nothing"), nil } filtered := false re := "" if parsed.Switches["r"].Value != nil { filtered = true re = parsed.Switches["r"].Str() if parsed.Switches["i"].Value != nil && parsed.Switches["i"].Value.(bool) { if !strings.HasPrefix(re, "(?i)") { re = "(?i)" + re } } } ma := parsed.Switches["ma"].Value.(time.Duration) if ma != 0 { filtered = true } minAge := parsed.Switches["minage"].Value.(time.Duration) if minAge != 0 { filtered = true } toID := int64(0) if parsed.Switches["to"].Value != nil { filtered = true toID = parsed.Switches["to"].Int64() } pe := false if parsed.Switches["nopin"].Value != nil && parsed.Switches["nopin"].Value.(bool) { pe = true filtered = true } attachments := false if parsed.Switches["a"].Value != nil && parsed.Switches["a"].Value.(bool) { attachments = true filtered = true } limitFetch := num if userFilter != 0 || filtered { limitFetch = num * 50 } if limitFetch > 1000 { limitFetch = 1000 } time.Sleep(time.Second) numDeleted, err := AdvancedDeleteMessages(parsed.Msg.ChannelID, userFilter, re, toID, ma, minAge, pe, attachments, num, limitFetch) return dcmd.NewTemporaryResponse(time.Second*5, fmt.Sprintf("Deleted %d message(s)! :')", numDeleted), true), err }, }, &commands.YAGCommand{ CustomEnabled: true, CmdCategory: commands.CategoryModeration, Name: "Reason", Description: "Add/Edit a modlog reason", RequiredArgs: 2, Arguments: []*dcmd.ArgDef{ &dcmd.ArgDef{Name: "Message ID", Type: dcmd.Int}, &dcmd.ArgDef{Name: "Reason", Type: dcmd.String}, }, RunFunc: func(parsed *dcmd.Data) (interface{}, error) { config, _, err := MBaseCmd(parsed, 0) if err != nil { return nil, err } _, err = MBaseCmdSecond(parsed, "", true, discordgo.PermissionKickMembers, nil, true) if err != nil { return nil, err } if config.ActionChannel == "" { return "No mod log channel set up", nil } msg, err := common.BotSession.ChannelMessage(config.IntActionChannel(), parsed.Args[0].Int64()) if err != nil { return nil, err } if msg.Author.ID != common.BotUser.ID { return "I didn't make that message", nil } if len(msg.Embeds) < 1 { return "This entry is either too old or you're trying to mess with me...", nil } embed := msg.Embeds[0] updateEmbedReason(parsed.Msg.Author, parsed.Args[1].Str(), embed) _, err = common.BotSession.ChannelMessageEditEmbed(config.IntActionChannel(), msg.ID, embed) if err != nil { return nil, err } return "👌", nil }, }, &commands.YAGCommand{ CustomEnabled: true, CmdCategory: commands.CategoryModeration, Name: "Warn", Description: "Warns a user, warnings are saved using the bot. Use -warnings to view them.", RequiredArgs: 2, Arguments: []*dcmd.ArgDef{ &dcmd.ArgDef{Name: "User", Type: dcmd.UserID}, &dcmd.ArgDef{Name: "Reason", Type: dcmd.String}, }, RunFunc: func(parsed *dcmd.Data) (interface{}, error) { config, target, err := MBaseCmd(parsed, parsed.Args[0].Int64()) if err != nil { return nil, err } _, err = MBaseCmdSecond(parsed, "", true, 0, config.WarnCmdRoles, config.WarnCommandsEnabled) if err != nil { return nil, err } err = WarnUser(config, parsed.GS.ID, parsed.CS, parsed.Msg, parsed.Msg.Author, target, parsed.Args[1].Str()) if err != nil { return nil, err } for _, plugin := range common.Plugins { fp, ok := plugin.(ModPlugin) if !ok { continue } ms, _ := bot.GetMember(parsed.GS.ID, target.ID) if ms != nil { go fp.HandleGuildMemberWarning(parsed.GS, ms) } } return GenericCmdResp(MAWarned, target, 0, false, true), nil }, }, &commands.YAGCommand{ CustomEnabled: true, CmdCategory: commands.CategoryModeration, Name: "Warnings", Description: "Lists warning of a user.", Aliases: []string{"Warns"}, RequiredArgs: 0, Arguments: []*dcmd.ArgDef{ &dcmd.ArgDef{Name: "User", Type: dcmd.UserID, Default: 0}, &dcmd.ArgDef{Name: "Page", Type: &dcmd.IntArg{Max: 10000}, Default: 0}, }, ArgSwitches: []*dcmd.ArgDef{ &dcmd.ArgDef{Switch: "id", Name: "Warning ID", Type: dcmd.Int}, }, RunFunc: func(parsed *dcmd.Data) (interface{}, error) { var err error config, _, err := MBaseCmd(parsed, 0) if err != nil { return nil, err } _, err = MBaseCmdSecond(parsed, "", true, discordgo.PermissionManageMessages, config.WarnCmdRoles, true) if err != nil { return nil, err } if parsed.Switches["id"].Value != nil { var warn []*WarningModel err = common.GORM.Where("guild_id = ? AND id = ?", parsed.GS.ID, parsed.Switches["id"].Int()).First(&warn).Error if err != nil && err != gorm.ErrRecordNotFound { return nil, err } if len(warn) == 0 { return fmt.Sprintf("Warning with given id : `%d` does not exist.", parsed.Switches["id"].Int()), nil } return &discordgo.MessageEmbed{ Title: fmt.Sprintf("Warning#%d - User : %s", warn[0].ID, warn[0].UserID), Description: fmt.Sprintf("`%20s` - **Reason** : %s", warn[0].CreatedAt.UTC().Format(time.RFC822), warn[0].Message), Footer: &discordgo.MessageEmbedFooter{Text: fmt.Sprintf("By: %s (%13s)", warn[0].AuthorUsernameDiscrim, warn[0].AuthorID)}, }, nil } page := parsed.Args[1].Int() if page < 1 { page = 1 } if parsed.Context().Value(paginatedmessages.CtxKeyNoPagination) != nil { return PaginateWarnings(parsed)(nil, page) } _, err = paginatedmessages.CreatePaginatedMessage(parsed.GS.ID, parsed.CS.ID, page, 0, PaginateWarnings(parsed)) return nil, err }, }, &commands.YAGCommand{ CustomEnabled: true, CmdCategory: commands.CategoryModeration, Name: "EditWarning", Description: "Edit a warning, id is the first number of each warning from the warnings command", RequiredArgs: 2, Arguments: []*dcmd.ArgDef{ &dcmd.ArgDef{Name: "Id", Type: dcmd.Int}, &dcmd.ArgDef{Name: "NewMessage", Type: dcmd.String}, }, RunFunc: func(parsed *dcmd.Data) (interface{}, error) { config, _, err := MBaseCmd(parsed, 0) if err != nil { return nil, err } _, err = MBaseCmdSecond(parsed, "", true, 0, config.WarnCmdRoles, config.WarnCommandsEnabled) if err != nil { return nil, err } rows := common.GORM.Model(WarningModel{}).Where("guild_id = ? AND id = ?", parsed.GS.ID, parsed.Args[0].Int()).Update( "message", fmt.Sprintf("%s (updated by %s#%s (%d))", parsed.Args[1].Str(), parsed.Msg.Author.Username, parsed.Msg.Author.Discriminator, parsed.Msg.Author.ID)).RowsAffected if rows < 1 { return "Failed updating, most likely couldn't find the warning", nil } return "👌", nil }, }, &commands.YAGCommand{ CustomEnabled: true, CmdCategory: commands.CategoryModeration, Name: "DelWarning", Aliases: []string{"dw"}, Description: "Deletes a warning, id is the first number of each warning from the warnings command", RequiredArgs: 1, Arguments: []*dcmd.ArgDef{ &dcmd.ArgDef{Name: "Id", Type: dcmd.Int}, }, RunFunc: func(parsed *dcmd.Data) (interface{}, error) { config, _, err := MBaseCmd(parsed, 0) if err != nil { return nil, err } _, err = MBaseCmdSecond(parsed, "", true, 0, config.WarnCmdRoles, config.WarnCommandsEnabled) if err != nil { return nil, err } rows := common.GORM.Where("guild_id = ? AND id = ?", parsed.GS.ID, parsed.Args[0].Int()).Delete(WarningModel{}).RowsAffected if rows < 1 { return "Failed deleting, most likely couldn't find the warning", nil } return "👌", nil }, }, &commands.YAGCommand{ CustomEnabled: true, CmdCategory: commands.CategoryModeration, Name: "ClearWarnings", Aliases: []string{"clw"}, Description: "Clears the warnings of a user", RequiredArgs: 1, Arguments: []*dcmd.ArgDef{ &dcmd.ArgDef{Name: "User", Type: dcmd.UserID}, }, RunFunc: func(parsed *dcmd.Data) (interface{}, error) { config, _, err := MBaseCmd(parsed, 0) if err != nil { return nil, err } _, err = MBaseCmdSecond(parsed, "", true, 0, config.WarnCmdRoles, config.WarnCommandsEnabled) if err != nil { return nil, err } userID := parsed.Args[0].Int64() rows := common.GORM.Where("guild_id = ? AND user_id = ?", parsed.GS.ID, userID).Delete(WarningModel{}).RowsAffected return fmt.Sprintf("Deleted %d warnings.", rows), nil }, }, &commands.YAGCommand{ CmdCategory: commands.CategoryModeration, Name: "Slowmode", Aliases: []string{"sm"}, Description: "Changes the channel slowmode during an optional duration.", RequiredArgs: 1, Cooldown: 10, Arguments: []*dcmd.ArgDef{ &dcmd.ArgDef{Name: "RateLimit", Type: dcmd.Int}, &dcmd.ArgDef{Name: "Duration", Type: &commands.DurationArg{}}, }, RunFunc: func(parsed *dcmd.Data) (interface{}, error) { config, _, err := MBaseCmd(parsed, 0) if err != nil { return nil, err } _, err = MBaseCmdSecond(parsed, "", true, discordgo.PermissionManageMessages, nil, config.SlowmodeCommandEnabled) if err != nil { return nil, err } duration := time.Duration(0) if parsed.Args[1].Value != nil { duration = parsed.Args[1].Value.(time.Duration) } if duration > 0 && duration < time.Minute { duration = time.Minute } RL := parsed.Args[0].Int() if RL > 21600 { RL = 21600 } out, err := SlowModeFunc(config, parsed.GS.ID, parsed.CS, parsed.Msg.Author, int(duration.Minutes()), RL) if err != nil { return nil, err } return out, nil }, }, &commands.YAGCommand{ CmdCategory: commands.CategoryModeration, Name: "TopWarnings", Aliases: []string{"topwarns"}, Description: "Shows ranked list of warnings on the server", Arguments: []*dcmd.ArgDef{ {Name: "Page", Type: dcmd.Int, Default: 0}, }, ArgSwitches: []*dcmd.ArgDef{ &dcmd.ArgDef{Switch: "id", Name: "List userIDs"}, }, RunFunc: paginatedmessages.PaginatedCommand(0, func(parsed *dcmd.Data, p *paginatedmessages.PaginatedMessage, page int) (*discordgo.MessageEmbed, error) { showUserIDs := false config, _, err := MBaseCmd(parsed, 0) if err != nil { return nil, err } _, err = MBaseCmdSecond(parsed, "", true, discordgo.PermissionManageMessages, config.WarnCmdRoles, true) if err != nil { return nil, err } if parsed.Switches["id"].Value != nil && parsed.Switches["id"].Value.(bool) { showUserIDs = true } offset := (page - 1) * 15 entries, err := TopWarns(parsed.GS.ID, offset, 15) if err != nil { return nil, err } if len(entries) < 1 && p != nil && p.LastResponse != nil { return nil, paginatedmessages.ErrNoResults } embed := &discordgo.MessageEmbed{ Title: "Ranked list of warnings", } out := "```\n# - Warns - User\n" for _, v := range entries { if !showUserIDs { user := v.Username if user == "" { user = "unknown ID:" + strconv.FormatInt(v.UserID, 10) } out += fmt.Sprintf("#%02d: %4d - %s\n", v.Rank, v.WarnCount, user) } else { out += fmt.Sprintf("#%02d: %4d - %d\n", v.Rank, v.WarnCount, v.UserID) } } out += "```\n" embed.Description = out return embed, nil }), }, &commands.YAGCommand{ CustomEnabled: true, CmdCategory: commands.CategoryModeration, Name: "GiveRole", Aliases: []string{"grole", "arole", "addrole"}, Description: "Gives a role to the specified member, with optional expiry", RequiredArgs: 2, Arguments: []*dcmd.ArgDef{ &dcmd.ArgDef{Name: "User", Type: dcmd.UserID}, &dcmd.ArgDef{Name: "Role", Type: dcmd.String}, }, ArgSwitches: []*dcmd.ArgDef{ &dcmd.ArgDef{Switch: "d", Default: time.Duration(0), Name: "Duration", Type: &commands.DurationArg{}}, }, RunFunc: func(parsed *dcmd.Data) (interface{}, error) { config, target, err := MBaseCmd(parsed, parsed.Args[0].Int64()) if err != nil { return nil, err } _, err = MBaseCmdSecond(parsed, "", true, discordgo.PermissionManageRoles, config.GiveRoleCmdRoles, config.GiveRoleCmdEnabled) if err != nil { return nil, err } member, err := bot.GetMember(parsed.GS.ID, target.ID) if err != nil || member == nil { return "Member not found", err } role := FindRole(parsed.GS, parsed.Args[1].Str()) if role == nil { return "Couldn't find the specified role", nil } parsed.GS.RLock() if !bot.IsMemberAboveRole(parsed.GS, parsed.MS, role) { parsed.GS.RUnlock() return "Can't give roles above you", nil } parsed.GS.RUnlock() dur := parsed.Switches["d"].Value.(time.Duration) if common.ContainsInt64Slice(member.Roles, role.ID) && dur <= 0 { return "That user already has that role", nil } err = common.AddRoleDS(member, role.ID) if err != nil { return nil, err } if dur > 0 { err := scheduledevents2.ScheduleRemoveRole(parsed.Context(), parsed.GS.ID, target.ID, role.ID, time.Now().Add(dur)) if err != nil { return nil, err } } scheduledevents2.CancelAddRole(parsed.Context(), parsed.GS.ID, parsed.Msg.Author.ID, role.ID) action := MAGiveRole action.Prefix = "Gave the role " + role.Name + " to " if config.GiveRoleCmdModlog && config.IntActionChannel() != 0 { if dur > 0 { action.Footer = "Duration: " + common.HumanizeDuration(common.DurationPrecisionMinutes, dur) } CreateModlogEmbed(config, parsed.Msg.Author, action, target, "", "") } return GenericCmdResp(action, target, dur, true, dur <= 0), nil }, }, &commands.YAGCommand{ CustomEnabled: true, CmdCategory: commands.CategoryModeration, Name: "RemoveRole", Aliases: []string{"rrole", "takerole", "trole"}, Description: "Removes the specified role from the target", RequiredArgs: 2, Arguments: []*dcmd.ArgDef{ &dcmd.ArgDef{Name: "User", Type: dcmd.UserID}, &dcmd.ArgDef{Name: "Role", Type: dcmd.String}, }, RunFunc: func(parsed *dcmd.Data) (interface{}, error) { config, target, err := MBaseCmd(parsed, parsed.Args[0].Int64()) if err != nil { return nil, err } _, err = MBaseCmdSecond(parsed, "", true, discordgo.PermissionManageRoles, config.GiveRoleCmdRoles, config.GiveRoleCmdEnabled) if err != nil { return nil, err } member, err := bot.GetMember(parsed.GS.ID, target.ID) if err != nil || member == nil { return "Member not found", err } role := FindRole(parsed.GS, parsed.Args[1].Str()) if role == nil { return "Couldn't find the specified role", nil } parsed.GS.RLock() if !bot.IsMemberAboveRole(parsed.GS, parsed.MS, role) { parsed.GS.RUnlock() return "Can't remove roles above you", nil } parsed.GS.RUnlock() err = common.RemoveRoleDS(member, role.ID) if err != nil { return nil, err } scheduledevents2.CancelRemoveRole(parsed.Context(), parsed.GS.ID, parsed.Msg.Author.ID, role.ID) action := MARemoveRole action.Prefix = "Removed the role " + role.Name + " from " if config.GiveRoleCmdModlog && config.IntActionChannel() != 0 { CreateModlogEmbed(config, parsed.Msg.Author, action, target, "", "") } return GenericCmdResp(action, target, 0, true, true), nil }, }, }
Functions ¶
func AddMemberMuteRole ¶
func AdvancedDeleteMessages ¶
func BanUserWithDuration ¶
func CreateDeleteLogEmbed ¶
func CreateModlogEmbed ¶
func CreateUpdateLogEmbed ¶
func DeleteMessages ¶
func FindAuditLogEntry ¶
func GenericCmdResp ¶
func GetMessage ¶
func HandleChannelCreateUpdate ¶
func HandleChannelCreateUpdate(evt *eventsystem.EventData) (retry bool, err error)
func HandleClearServerWarnings ¶
func HandleClearServerWarnings(w http.ResponseWriter, r *http.Request) (web.TemplateData, error)
Clear all server warnigns
func HandleGuildBanAddRemove ¶
func HandleGuildBanAddRemove(evt *eventsystem.EventData)
func HandleGuildCreate ¶
func HandleGuildCreate(evt *eventsystem.EventData)
func HandleGuildMemberRemove ¶
func HandleGuildMemberRemove(evt *eventsystem.EventData) (retry bool, err error)
func HandleGuildMemberUpdate ¶
func HandleGuildMemberUpdate(evt *eventsystem.EventData) (retry bool, err error)
func HandleMemberJoin ¶
func HandleMemberJoin(evt *eventsystem.EventData) (retry bool, err error)
func HandleMemberJoinLog ¶
func HandleMemberJoinLog(evt *eventsystem.EventData) (retry bool, err error)
func HandleMessageRemove ¶
func HandleMessageRemove(evt *eventsystem.EventData) (retry bool, err error)
func HandleMessageUpdate ¶
func HandleMessageUpdate(evt *eventsystem.EventData) (retry bool, err error)
func HandleModeration ¶
func HandleModeration(w http.ResponseWriter, r *http.Request) (web.TemplateData, error)
HandleModeration servers the moderation page itself
func HandlePostModeration ¶
func HandlePostModeration(w http.ResponseWriter, r *http.Request) (web.TemplateData, error)
HandlePostModeration update the settings
func LockMemberMuteMW ¶
func LockMemberMuteMW(next eventsystem.HandlerFunc) eventsystem.HandlerFunc
Since updating mutes are now a complex operation with removing roles and whatnot, to avoid weird bugs from happening we lock it so it can only be updated one place per user
func MBaseCmdSecond ¶
func MuteUnmuteUser ¶
func MuteUnmuteUser(config *Config, mute bool, guildID int64, channel *dstate.ChannelState, message *discordgo.Message, author *discordgo.User, reason string, member *dstate.MemberState, duration int) error
Unmut or mute a user, ignore duration if unmuting TODO: i don't think we need to track mutes in its own database anymore now with the new scheduled event system
func PaginateWarnings ¶
func PaginateWarnings(parsed *dcmd.Data) func(p *paginatedmessages.PaginatedMessage, page int) (*discordgo.MessageEmbed, error)
func RedisKeyBannedUser ¶
func RedisKeyLockedMute ¶
func RedisKeyMutedUser ¶
func RedisKeyUnbannedUser ¶
func RefreshMuteOverrides ¶
func RefreshMuteOverrides(guildID int64)
Refreshes the mute override on the channel, currently it only adds it.
func RegisterPlugin ¶
func RegisterPlugin()
func RemoveMemberMuteRole ¶
func SlowModeFunc ¶
func UnlockMute ¶
func UnlockMute(uID int64)
Types ¶
type ChannelRatelimitData ¶
type Config ¶
type Config struct { configstore.GuildConfigModel // Kick command KickEnabled bool KickCmdRoles pq.Int64Array `gorm:"type:bigint[]" valid:"role,true"` DeleteMessagesOnKick bool KickReasonOptional bool KickMessage string `valid:"template,5000"` // Ban BanEnabled bool BanCmdRoles pq.Int64Array `gorm:"type:bigint[]" valid:"role,true"` BanReasonOptional bool BanMessage string `valid:"template,5000"` DefaultBanDeleteDays sql.NullInt64 `gorm:"default:1" valid:"0,7"` // Mute/unmute MuteEnabled bool MuteCmdRoles pq.Int64Array `gorm:"type:bigint[]" valid:"role,true"` MuteRole string `valid:"role,true"` MuteDisallowReactionAdd bool MuteReasonOptional bool UnmuteReasonOptional bool MuteManageRole bool MuteRemoveRoles pq.Int64Array `gorm:"type:bigint[]" valid:"role,true"` MuteIgnoreChannels pq.Int64Array `gorm:"type:bigint[]" valid:"channel,true"` MuteMessage string `valid:"template,5000"` UnmuteMessage string `valid:"template,5000"` DefaultMuteDuration sql.NullInt64 `gorm:"default:10"` // Warn WarnCommandsEnabled bool WarnCmdRoles pq.Int64Array `gorm:"type:bigint[]" valid:"role,true"` WarnIncludeChannelLogs bool WarnSendToModlog bool WarnMessage string `valid:"template,5000"` // Misc CleanEnabled bool ReportEnabled bool ActionChannel string `valid:"channel,true"` ReportChannel string `valid:"channel,true"` LogChannel string `valid:"channel,true"` LogUnbans bool LogBans bool LogKicks bool `gorm:"default:true"` LogJoinLeave bool MessageDeleteLog bool MessageEditLog bool SlowmodeCommandEnabled bool GiveRoleCmdEnabled bool GiveRoleCmdModlog bool GiveRoleCmdRoles pq.Int64Array `gorm:"type:bigint[]" valid:"role,true"` }
func (*Config) IntActionChannel ¶
func (*Config) IntLogChannel ¶
func (*Config) IntMuteRole ¶
func (*Config) IntReportChannel ¶
type ModPlugin ¶
type ModPlugin interface {
HandleGuildMemberWarning(GS *dstate.GuildState, ms *dstate.MemberState)
}
type ModlogAction ¶
func (ModlogAction) String ¶
func (m ModlogAction) String() string
type MuteModel ¶
type MuteModel struct { common.SmallModel ExpiresAt time.Time GuildID int64 `gorm:"index"` UserID int64 AuthorID int64 Reason string RemovedRoles pq.Int64Array `gorm:"type:bigint[]"` }
type Plugin ¶
type Plugin struct{}
func (*Plugin) AddCommands ¶
func (p *Plugin) AddCommands()
func (*Plugin) AllFeatureFlags ¶
func (*Plugin) LoadServerHomeWidget ¶
func (p *Plugin) LoadServerHomeWidget(w http.ResponseWriter, r *http.Request) (web.TemplateData, error)
func (*Plugin) PluginInfo ¶
func (p *Plugin) PluginInfo() *common.PluginInfo
func (*Plugin) ShardMigrationReceive ¶
func (p *Plugin) ShardMigrationReceive(evt dshardorchestrator.EventType, data interface{})
type ScheduledUnbanData ¶
type ScheduledUnbanData struct {
UserID int64 `json:"user_id"`
}
type ScheduledUnmuteData ¶
type ScheduledUnmuteData struct {
UserID int64 `json:"user_id"`
}
type WarnRankEntry ¶
type WarningModel ¶
type WarningModel struct { common.SmallModel GuildID int64 `gorm:"index"` UserID string AuthorID string // Username and discrim for author incase he/she leaves AuthorUsernameDiscrim string Message string LogsLink string }
func (*WarningModel) TableName ¶
func (w *WarningModel) TableName() string
Click to show internal directories.
Click to hide internal directories.