From e905b79186419a873b581e64550a6ffab3e69b36 Mon Sep 17 00:00:00 2001 From: nitroflap Date: Sun, 19 Jun 2022 23:28:08 +0300 Subject: [PATCH 1/6] feat: auto moderation --- endpoints.go | 3 + eventhandlers.go | 96 ++++++++++++++++++++++++ events.go | 31 ++++++++ examples/auto_moderation/main.go | 111 ++++++++++++++++++++++++++++ restapi.go | 77 ++++++++++++++++++++ structs.go | 121 ++++++++++++++++++++++++++----- 6 files changed, 421 insertions(+), 18 deletions(-) create mode 100644 examples/auto_moderation/main.go diff --git a/endpoints.go b/endpoints.go index f5822da64..b0215fceb 100644 --- a/endpoints.go +++ b/endpoints.go @@ -68,6 +68,9 @@ var ( EndpointUserConnections = func(uID string) string { return EndpointUsers + uID + "/connections" } EndpointGuild = func(gID string) string { return EndpointGuilds + gID } + EndpointGuildAutoModeration = func(gID string) string { return EndpointGuild(gID) + "/auto-moderation" } + EndpointGuildAutoModerationRules = func(gID string) string { return EndpointGuildAutoModeration(gID) + "/rules" } + EndpointGuildAutoModerationRule = func(gID, rID string) string { return EndpointGuildAutoModerationRules(gID) + "/" + rID } EndpointGuildThreads = func(gID string) string { return EndpointGuild(gID) + "/threads" } EndpointGuildActiveThreads = func(gID string) string { return EndpointGuildThreads(gID) + "/active" } EndpointGuildPreview = func(gID string) string { return EndpointGuilds + gID + "/preview" } diff --git a/eventhandlers.go b/eventhandlers.go index f2ec080c3..36beefdf4 100644 --- a/eventhandlers.go +++ b/eventhandlers.go @@ -8,6 +8,10 @@ package discordgo // EventTypes surrounded by __ are synthetic and are internal to DiscordGo. const ( applicationCommandPermissionsUpdateEventType = "APPLICATION_COMMAND_PERMISSIONS_UPDATE" + autoModerationActionExecutionEventType = "AUTO_MODERATION_ACTION_EXECUTION" + autoModerationRuleCreateEventType = "AUTO_MODERATION_RULE_CREATE" + autoModerationRuleDeleteEventType = "AUTO_MODERATION_RULE_DELETE" + autoModerationRuleUpdateEventType = "AUTO_MODERATION_RULE_UPDATE" channelCreateEventType = "CHANNEL_CREATE" channelDeleteEventType = "CHANNEL_DELETE" channelPinsUpdateEventType = "CHANNEL_PINS_UPDATE" @@ -91,6 +95,86 @@ func (eh applicationCommandPermissionsUpdateEventHandler) Handle(s *Session, i i } } +// autoModerationActionExecutionEventHandler is an event handler for AutoModerationActionExecution events. +type autoModerationActionExecutionEventHandler func(*Session, *AutoModerationActionExecution) + +// Type returns the event type for AutoModerationActionExecution events. +func (eh autoModerationActionExecutionEventHandler) Type() string { + return autoModerationActionExecutionEventType +} + +// New returns a new instance of AutoModerationActionExecution. +func (eh autoModerationActionExecutionEventHandler) New() interface{} { + return &AutoModerationActionExecution{} +} + +// Handle is the handler for AutoModerationActionExecution events. +func (eh autoModerationActionExecutionEventHandler) Handle(s *Session, i interface{}) { + if t, ok := i.(*AutoModerationActionExecution); ok { + eh(s, t) + } +} + +// autoModerationRuleCreateEventHandler is an event handler for AutoModerationRuleCreate events. +type autoModerationRuleCreateEventHandler func(*Session, *AutoModerationRuleCreate) + +// Type returns the event type for AutoModerationRuleCreate events. +func (eh autoModerationRuleCreateEventHandler) Type() string { + return autoModerationRuleCreateEventType +} + +// New returns a new instance of AutoModerationRuleCreate. +func (eh autoModerationRuleCreateEventHandler) New() interface{} { + return &AutoModerationRuleCreate{} +} + +// Handle is the handler for AutoModerationRuleCreate events. +func (eh autoModerationRuleCreateEventHandler) Handle(s *Session, i interface{}) { + if t, ok := i.(*AutoModerationRuleCreate); ok { + eh(s, t) + } +} + +// autoModerationRuleDeleteEventHandler is an event handler for AutoModerationRuleDelete events. +type autoModerationRuleDeleteEventHandler func(*Session, *AutoModerationRuleDelete) + +// Type returns the event type for AutoModerationRuleDelete events. +func (eh autoModerationRuleDeleteEventHandler) Type() string { + return autoModerationRuleDeleteEventType +} + +// New returns a new instance of AutoModerationRuleDelete. +func (eh autoModerationRuleDeleteEventHandler) New() interface{} { + return &AutoModerationRuleDelete{} +} + +// Handle is the handler for AutoModerationRuleDelete events. +func (eh autoModerationRuleDeleteEventHandler) Handle(s *Session, i interface{}) { + if t, ok := i.(*AutoModerationRuleDelete); ok { + eh(s, t) + } +} + +// autoModerationRuleUpdateEventHandler is an event handler for AutoModerationRuleUpdate events. +type autoModerationRuleUpdateEventHandler func(*Session, *AutoModerationRuleUpdate) + +// Type returns the event type for AutoModerationRuleUpdate events. +func (eh autoModerationRuleUpdateEventHandler) Type() string { + return autoModerationRuleUpdateEventType +} + +// New returns a new instance of AutoModerationRuleUpdate. +func (eh autoModerationRuleUpdateEventHandler) New() interface{} { + return &AutoModerationRuleUpdate{} +} + +// Handle is the handler for AutoModerationRuleUpdate events. +func (eh autoModerationRuleUpdateEventHandler) Handle(s *Session, i interface{}) { + if t, ok := i.(*AutoModerationRuleUpdate); ok { + eh(s, t) + } +} + // channelCreateEventHandler is an event handler for ChannelCreate events. type channelCreateEventHandler func(*Session, *ChannelCreate) @@ -1297,6 +1381,14 @@ func handlerForInterface(handler interface{}) EventHandler { return interfaceEventHandler(v) case func(*Session, *ApplicationCommandPermissionsUpdate): return applicationCommandPermissionsUpdateEventHandler(v) + case func(*Session, *AutoModerationActionExecution): + return autoModerationActionExecutionEventHandler(v) + case func(*Session, *AutoModerationRuleCreate): + return autoModerationRuleCreateEventHandler(v) + case func(*Session, *AutoModerationRuleDelete): + return autoModerationRuleDeleteEventHandler(v) + case func(*Session, *AutoModerationRuleUpdate): + return autoModerationRuleUpdateEventHandler(v) case func(*Session, *ChannelCreate): return channelCreateEventHandler(v) case func(*Session, *ChannelDelete): @@ -1426,6 +1518,10 @@ func handlerForInterface(handler interface{}) EventHandler { func init() { registerInterfaceProvider(applicationCommandPermissionsUpdateEventHandler(nil)) + registerInterfaceProvider(autoModerationActionExecutionEventHandler(nil)) + registerInterfaceProvider(autoModerationRuleCreateEventHandler(nil)) + registerInterfaceProvider(autoModerationRuleDeleteEventHandler(nil)) + registerInterfaceProvider(autoModerationRuleUpdateEventHandler(nil)) registerInterfaceProvider(channelCreateEventHandler(nil)) registerInterfaceProvider(channelDeleteEventHandler(nil)) registerInterfaceProvider(channelPinsUpdateEventHandler(nil)) diff --git a/events.go b/events.go index 17c78281f..3f62eb43a 100644 --- a/events.go +++ b/events.go @@ -406,3 +406,34 @@ type InviteDelete struct { type ApplicationCommandPermissionsUpdate struct { *GuildApplicationCommandPermissions } + +// AutoModerationRuleCreate is the data for an AutoModerationRuleCreate event. +type AutoModerationRuleCreate struct { + *AutoModerationRule +} + +// AutoModerationRuleUpdate is the data for an AutoModerationRuleUpdate event. +type AutoModerationRuleUpdate struct { + *AutoModerationRule + // TODO: BeforeUpdate *AutoModerationRule +} + +// AutoModerationRuleDelete is the data for an AutoModerationRuleDelete event. +type AutoModerationRuleDelete struct { + *AutoModerationRule + // TODO: BeforeDelete *AutoModerationRule +} + +// AutoModerationActionExecution is the data for an AutoModerationActionExecution event. +type AutoModerationActionExecution struct { + GuildID string `json:"guild_id"` + Action AutoModerationAction `json:"action"` + RuleID string `json:"rule_id"` + RuleTriggerType AutoModerationRuleTriggerType `json:"rule_trigger_type"` + ChannelID string `json:"channel_id"` + MessageID string `json:"message_id"` + AlertSystemMessageID string `json:"alert_system_message_id"` + Content string `json:"content"` + MatchedKeyword string `json:"matched_keyword"` + MatchedContent string `json:"matched_content"` +} diff --git a/examples/auto_moderation/main.go b/examples/auto_moderation/main.go new file mode 100644 index 000000000..52b64545c --- /dev/null +++ b/examples/auto_moderation/main.go @@ -0,0 +1,111 @@ +package main + +import ( + "flag" + "fmt" + "log" + "os" + "os/signal" + "sync" + + "github.com/bwmarrin/discordgo" +) + +// Command line flags +var ( + BotToken = flag.String("token", "", "Bot authorization token") + GuildID = flag.String("guild", "", "ID of the testing guild") + ChannelID = flag.String("channel", "", "ID of the testing channel") +) + +func init() { flag.Parse() } + +func main() { + session, _ := discordgo.New("Bot " + *BotToken) + session.Identify.Intents |= discordgo.IntentAutoModerationExecution + + enabled := true + rule, err := session.AutoModerationRuleCreate(*GuildID, &discordgo.AutoModerationRule{ + Name: "Auto Moderation example", + EventType: discordgo.AutoModerationEventMessageSend, + TriggerType: discordgo.AutoModerationEventTriggerKeyword, + TriggerMetadata: &discordgo.AutoModerationTriggerMetadata{ + KeywordFilter: []string{"*cat*"}, + }, + + Enabled: &enabled, + Actions: []discordgo.AutoModerationAction{ + {Type: discordgo.AutoModerationRuleActionBlockMessage}, + }, + }) + if err != nil { + panic(err) + } + fmt.Println("Successfully created the rule") + defer session.AutoModerationRuleDelete(*GuildID, rule.ID) + session.AddHandlerOnce(func(s *discordgo.Session, e *discordgo.AutoModerationActionExecution) { + _, err = session.AutoModerationRuleEdit(*GuildID, rule.ID, &discordgo.AutoModerationRule{ + TriggerMetadata: &discordgo.AutoModerationTriggerMetadata{ + KeywordFilter: []string{"cat"}, + }, + Actions: []discordgo.AutoModerationAction{ + {Type: discordgo.AutoModerationRuleActionTimeout, Metadata: &discordgo.AutoModerationActionMetadata{Duration: 60}}, + {Type: discordgo.AutoModerationRuleActionSendAlertMessage, Metadata: &discordgo.AutoModerationActionMetadata{ + ChannelID: e.ChannelID, + }}, + }, + }) + if err != nil { + session.AutoModerationRuleDelete(*GuildID, rule.ID) + panic(err) + } + s.ChannelMessageSend(e.ChannelID, "Congratulations! You have just triggered an auto moderation rule.\n"+ + "The current trigger can match anywhere in the word, so even if you write the trigger word as a part of another word, it will still match.\n"+ + "The rule has now been changed, now the trigger matches only in the full words.\n"+ + "Additionally, when you send a message, an alert will be sent to this channel and you will be **timed out** for a minute.\n") + var counter int + var counterMutex sync.Mutex + session.AddHandler(func(s *discordgo.Session, e *discordgo.AutoModerationActionExecution) { + action := "unknown" + switch e.Action.Type { + case discordgo.AutoModerationRuleActionBlockMessage: + action = "block message" + case discordgo.AutoModerationRuleActionSendAlertMessage: + action = "send alert message into <#" + e.Action.Metadata.ChannelID + ">" + case discordgo.AutoModerationRuleActionTimeout: + action = "timeout" + } + counterMutex.Lock() + counter++ + if counter == 1 { + counterMutex.Unlock() + s.ChannelMessageSend(e.ChannelID, "Nothing has changed, right? "+ + "Well, since separate gateway events are fired per each action (current is "+action+"), "+ + "you'll see a second message about an action pop up soon") + } else if counter == 2 { + counterMutex.Unlock() + s.ChannelMessageSend(e.ChannelID, "Now the second ("+action+") action got executed.") + s.ChannelMessageSend(e.ChannelID, "And... you've made it! That's the end of the example.\n"+ + "For more information about the automod and how to use it, "+ + "you can visit the official Discord docs: https://discord.dev/resources/auto-moderation or ask in our server: https://discord.gg/6dzbuDpSWY", + ) + + session.Close() + session.AutoModerationRuleDelete(*GuildID, rule.ID) + os.Exit(0) + } + + }) + }) + err = session.Open() + if err != nil { + log.Fatalf("Cannot open the session: %v", err) + } + defer session.Close() + + stop := make(chan os.Signal, 1) + signal.Notify(stop, os.Interrupt) + <-stop + log.Println("Graceful shutdown") + +} diff --git a/restapi.go b/restapi.go index 8c700bed8..72daaa702 100644 --- a/restapi.go +++ b/restapi.go @@ -3111,3 +3111,80 @@ func (s *Session) GuildScheduledEventUsers(guildID, eventID string, limit int, w err = unmarshal(body, &st) return } + +// ---------------------------------------------------------------------- +// Functions specific to auto moderation +// ---------------------------------------------------------------------- + +// AutoModerationRules returns a list of auto moderation rules. +// guildID : ID of the guild +func (s *Session) AutoModerationRules(guildID string) (st []*AutoModerationRule, err error) { + endpoint := EndpointGuildAutoModerationRules(guildID) + + var body []byte + body, err = s.RequestWithBucketID("GET", endpoint, nil, endpoint) + if err != nil { + return + } + + err = unmarshal(body, &st) + return +} + +// AutoModerationRule returns an auto moderation rule. +// guildID : ID of the guild +// ruleID : ID of the auto moderation rule +func (s *Session) AutoModerationRule(guildID, ruleID string) (st *AutoModerationRule, err error) { + endpoint := EndpointGuildAutoModerationRule(guildID, ruleID) + + var body []byte + body, err = s.RequestWithBucketID("GET", endpoint, nil, endpoint) + if err != nil { + return + } + + err = unmarshal(body, &st) + return +} + +// AutoModerationRuleCreate creates an auto moderation rule with the given data and returns it. +// guildID : ID of the guild +// rule : Rule data +func (s *Session) AutoModerationRuleCreate(guildID string, rule *AutoModerationRule) (st *AutoModerationRule, err error) { + endpoint := EndpointGuildAutoModerationRules(guildID) + + var body []byte + body, err = s.RequestWithBucketID("POST", endpoint, rule, endpoint) + if err != nil { + return + } + + err = unmarshal(body, &st) + return +} + +// AutoModerationRuleEdit edits and returns the updated auto moderation rule. +// guildID : ID of the guild +// ruleID : ID of the auto moderation rule +// rule : New rule data +func (s *Session) AutoModerationRuleEdit(guildID, ruleID string, rule *AutoModerationRule) (st *AutoModerationRule, err error) { + endpoint := EndpointGuildAutoModerationRule(guildID, ruleID) + + var body []byte + body, err = s.RequestWithBucketID("PATCH", endpoint, rule, endpoint) + if err != nil { + return + } + + err = unmarshal(body, &st) + return +} + +// AutoModerationRuleDelete deletes an auto moderation rule. +// guildID : ID of the guild +// ruleID : ID of the auto moderation rule +func (s *Session) AutoModerationRuleDelete(guildID, ruleID string) (err error) { + endpoint := EndpointGuildAutoModerationRule(guildID, ruleID) + _, err = s.RequestWithBucketID("DELETE", endpoint, nil, endpoint) + return +} diff --git a/structs.go b/structs.go index 268933d6c..2e7f5a9c6 100644 --- a/structs.go +++ b/structs.go @@ -1303,6 +1303,87 @@ type GuildBan struct { User *User `json:"user"` } +// AutoModerationRule stores data for an auto moderation rule. +type AutoModerationRule struct { + ID string `json:"id,omitempty"` + GuildID string `json:"guild_id,omitempty"` + Name string `json:"name,omitempty"` + CreatorID string `json:"creator_id,omitempty"` + EventType AutoModerationRuleEventType `json:"event_type,omitempty"` + TriggerType AutoModerationRuleTriggerType `json:"trigger_type,omitempty"` + TriggerMetadata *AutoModerationTriggerMetadata `json:"trigger_metadata,omitempty"` + Actions []AutoModerationAction `json:"actions,omitempty"` + Enabled *bool `json:"enabled,omitempty"` + ExemptRoles *[]string `json:"exempt_roles,omitempty"` + ExemptChannels *[]string `json:"exempt_channels,omitempty"` +} + +// AutoModerationRuleEventType indicates in what event context a rule should be checked. +type AutoModerationRuleEventType int + +// Auto moderation rule event types. +const ( + AutoModerationEventMessageSend AutoModerationRuleEventType = 1 +) + +// AutoModerationRuleTriggerType represents the type of content which can trigger the rule. +type AutoModerationRuleTriggerType int + +// Auto moderation rule trigger types. +const ( + AutoModerationEventTriggerKeyword AutoModerationRuleTriggerType = 1 + AutoModerationEventTriggerHarmfulLink AutoModerationRuleTriggerType = 2 + AutoModerationEventTriggerSpam AutoModerationRuleTriggerType = 3 + AutoModerationEventTriggerKeywordPreset AutoModerationRuleTriggerType = 4 +) + +// AutoModerationKeywordPreset represents an internally pre-defined wordset. +type AutoModerationKeywordPreset uint + +// Auto moderation keyword presets. +const ( + AutoModerationKeywordPresetProfanity AutoModerationKeywordPreset = 1 + AutoModerationKeywordPresetSexualContent AutoModerationKeywordPreset = 2 + AutoModerationKeywordPresetSlurs AutoModerationKeywordPreset = 3 +) + +// AutoModerationTriggerMetadata represents additional metadata used to determine whether rule should be triggered. +type AutoModerationTriggerMetadata struct { + // Substrings which will be searched for in content. + // NOTE: should be only used with keyword trigger type. + KeywordFilter []string `json:"keyword_filter,omitempty"` + // Internally pre-defined wordsets which will be searched for in content. + // NOTE: should be only used with keyword preset trigger type. + Presets []AutoModerationKeywordPreset `json:"presets,omitempty"` +} + +// AutoModerationActionType represents an action which will execute whenever a rule is triggered. +type AutoModerationActionType int + +// Auto moderation actions types. +const ( + AutoModerationRuleActionBlockMessage AutoModerationActionType = 1 + AutoModerationRuleActionSendAlertMessage AutoModerationActionType = 2 + AutoModerationRuleActionTimeout AutoModerationActionType = 3 +) + +// AutoModerationActionMetadata represents additional metadata needed during execution for a specific action type. +type AutoModerationActionMetadata struct { + // Channel to which user content should be logged. + // NOTE: should be only used with send alert message action type. + ChannelID string `json:"channel_id,omitempty"` + + // Timeout duration in seconds (maximum of 2419200 - 4 weeks). + // NOTE: should be only used with timeout action type. + Duration int `json:"duration_seconds,omitempty"` +} + +// AutoModerationAction stores data for an auto moderation action. +type AutoModerationAction struct { + Type AutoModerationActionType `json:"type"` + Metadata *AutoModerationActionMetadata `json:"metadata,omitempty"` +} + // A GuildEmbed stores data for a guild embed. type GuildEmbed struct { Enabled bool `json:"enabled"` @@ -2061,23 +2142,25 @@ type Intent int // Constants for the different bit offsets of intents const ( - IntentGuilds Intent = 1 << 0 - IntentGuildMembers Intent = 1 << 1 - IntentGuildBans Intent = 1 << 2 - IntentGuildEmojis Intent = 1 << 3 - IntentGuildIntegrations Intent = 1 << 4 - IntentGuildWebhooks Intent = 1 << 5 - IntentGuildInvites Intent = 1 << 6 - IntentGuildVoiceStates Intent = 1 << 7 - IntentGuildPresences Intent = 1 << 8 - IntentGuildMessages Intent = 1 << 9 - IntentGuildMessageReactions Intent = 1 << 10 - IntentGuildMessageTyping Intent = 1 << 11 - IntentDirectMessages Intent = 1 << 12 - IntentDirectMessageReactions Intent = 1 << 13 - IntentDirectMessageTyping Intent = 1 << 14 - IntentMessageContent Intent = 1 << 15 - IntentGuildScheduledEvents Intent = 1 << 16 + IntentGuilds Intent = 1 << 0 + IntentGuildMembers Intent = 1 << 1 + IntentGuildBans Intent = 1 << 2 + IntentGuildEmojis Intent = 1 << 3 + IntentGuildIntegrations Intent = 1 << 4 + IntentGuildWebhooks Intent = 1 << 5 + IntentGuildInvites Intent = 1 << 6 + IntentGuildVoiceStates Intent = 1 << 7 + IntentGuildPresences Intent = 1 << 8 + IntentGuildMessages Intent = 1 << 9 + IntentGuildMessageReactions Intent = 1 << 10 + IntentGuildMessageTyping Intent = 1 << 11 + IntentDirectMessages Intent = 1 << 12 + IntentDirectMessageReactions Intent = 1 << 13 + IntentDirectMessageTyping Intent = 1 << 14 + IntentMessageContent Intent = 1 << 15 + IntentGuildScheduledEvents Intent = 1 << 16 + IntentAutoModerationConfiguration Intent = 1 << 20 + IntentAutoModerationExecution Intent = 1 << 21 // TODO: remove when compatibility is not needed @@ -2112,7 +2195,9 @@ const ( IntentDirectMessages | IntentDirectMessageReactions | IntentDirectMessageTyping | - IntentGuildScheduledEvents + IntentGuildScheduledEvents | + IntentAutoModerationConfiguration | + IntentAutoModerationExecution IntentsAll = IntentsAllWithoutPrivileged | IntentGuildMembers | From a046cb8aff8cbe213295bdc8216e2ef91157dc66 Mon Sep 17 00:00:00 2001 From: nitroflap Date: Sun, 26 Jun 2022 19:02:22 +0300 Subject: [PATCH 2/6] feat(examples/automod): add message content intent --- examples/auto_moderation/main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/auto_moderation/main.go b/examples/auto_moderation/main.go index 52b64545c..0dc5bc289 100644 --- a/examples/auto_moderation/main.go +++ b/examples/auto_moderation/main.go @@ -23,6 +23,7 @@ func init() { flag.Parse() } func main() { session, _ := discordgo.New("Bot " + *BotToken) session.Identify.Intents |= discordgo.IntentAutoModerationExecution + session.Identify.Intents |= discordgo.IntentMessageContent enabled := true rule, err := session.AutoModerationRuleCreate(*GuildID, &discordgo.AutoModerationRule{ From 28663f32ff1a419998424bbccdd1f9afc16faff1 Mon Sep 17 00:00:00 2001 From: Fedor Lapshin Date: Sun, 3 Jul 2022 01:21:20 +0000 Subject: [PATCH 3/6] style(examples/automod): newline between sections --- examples/auto_moderation/main.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/examples/auto_moderation/main.go b/examples/auto_moderation/main.go index 0dc5bc289..66fbbcbdc 100644 --- a/examples/auto_moderation/main.go +++ b/examples/auto_moderation/main.go @@ -42,8 +42,10 @@ func main() { if err != nil { panic(err) } + fmt.Println("Successfully created the rule") defer session.AutoModerationRuleDelete(*GuildID, rule.ID) + session.AddHandlerOnce(func(s *discordgo.Session, e *discordgo.AutoModerationActionExecution) { _, err = session.AutoModerationRuleEdit(*GuildID, rule.ID, &discordgo.AutoModerationRule{ TriggerMetadata: &discordgo.AutoModerationTriggerMetadata{ @@ -60,10 +62,12 @@ func main() { session.AutoModerationRuleDelete(*GuildID, rule.ID) panic(err) } + s.ChannelMessageSend(e.ChannelID, "Congratulations! You have just triggered an auto moderation rule.\n"+ "The current trigger can match anywhere in the word, so even if you write the trigger word as a part of another word, it will still match.\n"+ "The rule has now been changed, now the trigger matches only in the full words.\n"+ "Additionally, when you send a message, an alert will be sent to this channel and you will be **timed out** for a minute.\n") + var counter int var counterMutex sync.Mutex session.AddHandler(func(s *discordgo.Session, e *discordgo.AutoModerationActionExecution) { @@ -76,6 +80,7 @@ func main() { case discordgo.AutoModerationRuleActionTimeout: action = "timeout" } + counterMutex.Lock() counter++ if counter == 1 { @@ -95,9 +100,9 @@ func main() { session.AutoModerationRuleDelete(*GuildID, rule.ID) os.Exit(0) } - }) }) + err = session.Open() if err != nil { log.Fatalf("Cannot open the session: %v", err) From a93f3eac7ed143a52c318f2957fd39065e81c75d Mon Sep 17 00:00:00 2001 From: Fedor Lapshin Date: Sun, 3 Jul 2022 01:22:39 +0000 Subject: [PATCH 4/6] feat(AutoModerationActionExecution): add user id Add user_id field to AutoModerationActionExecution event. --- events.go | 1 + 1 file changed, 1 insertion(+) diff --git a/events.go b/events.go index 3f62eb43a..beb685b84 100644 --- a/events.go +++ b/events.go @@ -430,6 +430,7 @@ type AutoModerationActionExecution struct { Action AutoModerationAction `json:"action"` RuleID string `json:"rule_id"` RuleTriggerType AutoModerationRuleTriggerType `json:"rule_trigger_type"` + UserID string `json:"user_id"` ChannelID string `json:"channel_id"` MessageID string `json:"message_id"` AlertSystemMessageID string `json:"alert_system_message_id"` From 6a8c9e0f592bdb2e73f1094ce862c9098526678a Mon Sep 17 00:00:00 2001 From: Fedor Lapshin Date: Sun, 3 Jul 2022 01:25:52 +0000 Subject: [PATCH 5/6] refactor(events): remove todos Remove TODO comments for AutoModerationRuleUpdate and AutoModerationRuleDelete. --- events.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/events.go b/events.go index beb685b84..5cb7622d7 100644 --- a/events.go +++ b/events.go @@ -415,13 +415,11 @@ type AutoModerationRuleCreate struct { // AutoModerationRuleUpdate is the data for an AutoModerationRuleUpdate event. type AutoModerationRuleUpdate struct { *AutoModerationRule - // TODO: BeforeUpdate *AutoModerationRule } // AutoModerationRuleDelete is the data for an AutoModerationRuleDelete event. type AutoModerationRuleDelete struct { *AutoModerationRule - // TODO: BeforeDelete *AutoModerationRule } // AutoModerationActionExecution is the data for an AutoModerationActionExecution event. From e714305bb6c767f6af27ae8b038e0836c6bd3a87 Mon Sep 17 00:00:00 2001 From: Fedor Lapshin Date: Sun, 3 Jul 2022 01:27:50 +0000 Subject: [PATCH 6/6] feat(AutoModerationEventMessageSend): doc comment Add documentation comment to AutoModerationEventMessageSend constant. --- structs.go | 1 + 1 file changed, 1 insertion(+) diff --git a/structs.go b/structs.go index 2e7f5a9c6..8631feced 100644 --- a/structs.go +++ b/structs.go @@ -1323,6 +1323,7 @@ type AutoModerationRuleEventType int // Auto moderation rule event types. const ( + // AutoModerationEventMessageSend is checked when a member sends or edits a message in the guild AutoModerationEventMessageSend AutoModerationRuleEventType = 1 )