From 18bcc3286869beae274695790aa6f6722e40666b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20Susa=C3=B1a?= Date: Tue, 2 Aug 2022 21:17:46 -0400 Subject: [PATCH] Methods for AutoModeration (#90) * feat(core): AutoModeration prototypes * feat(core): Guild fetch mod rules --- packages/api-types/src/v10/index.ts | 2 + packages/core/src/structures/automod.ts | 120 +++++++++++++++++++++--- packages/core/src/structures/guilds.ts | 11 +++ 3 files changed, 122 insertions(+), 11 deletions(-) diff --git a/packages/api-types/src/v10/index.ts b/packages/api-types/src/v10/index.ts index 60a8386..d689209 100644 --- a/packages/api-types/src/v10/index.ts +++ b/packages/api-types/src/v10/index.ts @@ -1494,6 +1494,8 @@ export interface DiscordAutoModerationRuleTriggerMetadata { keyword_filter?: string[]; /** The pre-defined lists of words to match from. Only present when TriggerType.KeywordPreset */ presets?: DiscordAutoModerationRuleTriggerMetadataPresets[]; + /** substrings which will be exempt from triggering the preset trigger type */ + allow_list?: string[]; } export enum DiscordAutoModerationRuleTriggerMetadataPresets { diff --git a/packages/core/src/structures/automod.ts b/packages/core/src/structures/automod.ts index e11a3c6..bc169ef 100644 --- a/packages/core/src/structures/automod.ts +++ b/packages/core/src/structures/automod.ts @@ -1,18 +1,20 @@ -import type { Model } from './base'; -import type { Session } from '../biscuit'; -import type { Snowflake } from '../snowflakes'; -import type { +import { Model } from './base'; +import { Session } from '../biscuit'; +import { Snowflake } from '../snowflakes'; +import { AutoModerationActionType, AutoModerationEventTypes, AutoModerationTriggerTypes, DiscordAutoModerationRule, DiscordAutoModerationRuleTriggerMetadataPresets, DiscordAutoModerationActionExecution, + AUTO_MODERATION_RULES } from '@biscuitland/api-types'; export interface AutoModerationRuleTriggerMetadata { keywordFilter?: string[]; presets?: DiscordAutoModerationRuleTriggerMetadataPresets[]; + allowList?: string[]; } export interface ActionMetadata { @@ -25,6 +27,18 @@ export interface AutoModerationAction { metadata: ActionMetadata; } +/**@link https://discord.com/developers/docs/resources/auto-moderation#create-auto-moderation-rule-json-params */ +export interface CreateAutoModerationRule { + name: string; + eventType: 1; + triggerType: AutoModerationTriggerTypes; + triggerMetadata?: AutoModerationRuleTriggerMetadata; + actions: AutoModerationAction[]; + enabled?: boolean; + exemptRoles?: Snowflake[]; + exemptChannels?: Snowflake[]; +} + export class AutoModerationRule implements Model { constructor(session: Session, data: DiscordAutoModerationRule) { this.session = session; @@ -37,14 +51,15 @@ export class AutoModerationRule implements Model { this.triggerMetadata = { keywordFilter: data.trigger_metadata.keyword_filter, presets: data.trigger_metadata.presets, + allowList: data.trigger_metadata.allow_list }; this.actions = data.actions.map(action => Object.create({ type: action.type, metadata: { channelId: action.metadata.channel_id, - durationSeconds: action.metadata.duration_seconds, - }, + durationSeconds: action.metadata.duration_seconds + } }) ); this.enabled = !!data.enabled; @@ -64,19 +79,102 @@ export class AutoModerationRule implements Model { enabled: boolean; exemptRoles: Snowflake[]; exemptChannels: Snowflake[]; + + async getRules( + ruleId?: Snowflake + ): Promise { + const request = await this.session.rest.get< + DiscordAutoModerationRule | DiscordAutoModerationRule[] + >(AUTO_MODERATION_RULES(this.guildId, ruleId)); + if (Array.isArray(request)) + return request.map( + amr => new AutoModerationRule(this.session, amr) + ); + return new AutoModerationRule(this.session, request); + } + + async createRule(options: CreateAutoModerationRule) { + const request = await this.session.rest.post( + AUTO_MODERATION_RULES(this.guildId), + { + name: options.name, + event_type: options.eventType, + trigger_type: options.triggerType, + trigger_metadata: options.triggerMetadata, + actions: options.actions + ? options.actions.map(x => + Object.assign( + {}, + { + type: x.type, + metadata: { + channel_id: x.metadata.channelId, + duration_seconds: + x.metadata.durationSeconds + } + } + ) + ) + : undefined, + enabled: !!options.enabled, + exempt_roles: options.exemptRoles, + exempt_channels: options.exemptChannels + } + ); + return new AutoModerationRule(this.session, request); + } + + async editRule( + ruleId = this.id, + options: Partial + ) { + const request = await this.session.rest.patch< + DiscordAutoModerationRule + >(AUTO_MODERATION_RULES(this.guildId, ruleId), { + name: options.name, + event_type: options.eventType, + trigger_type: options.triggerType, + trigger_metadata: options.triggerMetadata, + actions: options.actions + ? options.actions.map(x => + Object.assign( + {}, + { + type: x.type, + metadata: { + channel_id: x.metadata.channelId, + duration_seconds: x.metadata.durationSeconds + } + } + ) + ) + : undefined, + enabled: !!options.enabled, + exempt_roles: options.exemptRoles, + exempt_channels: options.exemptChannels + }); + return new AutoModerationRule(this.session, request); + } + + async deleteRule(ruleId = this.id): Promise { + await this.session.rest.delete( + AUTO_MODERATION_RULES(this.guildId, ruleId) + ); + return; + } } export class AutoModerationExecution { constructor(session: Session, data: DiscordAutoModerationActionExecution) { this.session = session; this.guildId = data.guild_id; - this.action = Object.create({ + this.action = { type: data.action.type, metadata: { - channelId: data.action.metadata.channel_id, - durationSeconds: data.action.metadata.duration_seconds, - }, - }); + channelId: data.action.metadata.channel_id as string, + durationSeconds: data.action.metadata.duration_seconds as number + } + }; this.ruleId = data.rule_id; this.ruleTriggerType = data.rule_trigger_type; this.userId = data.user_id; diff --git a/packages/core/src/structures/guilds.ts b/packages/core/src/structures/guilds.ts index 87bbb86..781e20b 100644 --- a/packages/core/src/structures/guilds.ts +++ b/packages/core/src/structures/guilds.ts @@ -68,6 +68,7 @@ import { User } from './user'; import { Widget } from './widget'; import { Sticker } from './sticker'; import { WelcomeScreen } from './welcome'; +import { AutoModerationRule } from './automod'; /** BaseGuild */ /** @@ -1119,6 +1120,16 @@ export class Guild extends BaseGuild implements Model { return new Guild(this.session, guild); } + /** + * gets the auto moderation rules for the guild. + * @see {@link AutoModerationRule#getRules} sames + * @param ruleId The optional rule id + * @returns + */ + fetchAutoModerationRules(ruleId?: Snowflake): Promise { + return AutoModerationRule.prototype.getRules.call({session: this.session, guildId: this.id}, ruleId); + } + /** * gets the voice regions available for the guild. * @see {@link DiscordVoiceRegion}