feat: Safety alerts channel and mention raid protection (#9073)

* feat: safety alerts channel and mention raid protection

* feat: add raw types

* Apply suggestions from code review

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>

* docs: update guild features

---------

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
This commit is contained in:
Jaw0r3k
2023-05-07 14:44:44 +02:00
committed by GitHub
parent c5a42ed5ec
commit 5057f04304
5 changed files with 119 additions and 1 deletions

View File

@@ -58,6 +58,7 @@ class AutoModerationRuleManager extends CachedManager {
* @property {string[]} [allowList] The substrings that will be exempt from triggering * @property {string[]} [allowList] The substrings that will be exempt from triggering
* {@link AutoModerationRuleTriggerType.KEYWORD} and {@link AutoModerationRuleTriggerType.KEYWORD_PRESET} * {@link AutoModerationRuleTriggerType.KEYWORD} and {@link AutoModerationRuleTriggerType.KEYWORD_PRESET}
* @property {?number} [mentionTotalLimit] The total number of role & user mentions allowed per message * @property {?number} [mentionTotalLimit] The total number of role & user mentions allowed per message
* @property {boolean} [mentionRaidProtectionEnabled] Whether to automatically detect mention raids
*/ */
/** /**
@@ -126,6 +127,7 @@ class AutoModerationRuleManager extends CachedManager {
), ),
allow_list: triggerMetadata.allowList, allow_list: triggerMetadata.allowList,
mention_total_limit: triggerMetadata.mentionTotalLimit, mention_total_limit: triggerMetadata.mentionTotalLimit,
mention_raid_protection_enabled: triggerMetadata.mentionRaidProtectionEnabled,
}, },
actions: actions.map(action => ({ actions: actions.map(action => ({
type: typeof action.type === 'number' ? action.type : AutoModerationActionTypes[action.type], type: typeof action.type === 'number' ? action.type : AutoModerationActionTypes[action.type],
@@ -188,6 +190,7 @@ class AutoModerationRuleManager extends CachedManager {
), ),
allow_list: triggerMetadata.allowList, allow_list: triggerMetadata.allowList,
mention_total_limit: triggerMetadata.mentionTotalLimit, mention_total_limit: triggerMetadata.mentionTotalLimit,
mention_raid_protection_enabled: triggerMetadata.mentionRaidProtectionEnabled,
}, },
actions: actions?.map(action => ({ actions: actions?.map(action => ({
type: typeof action.type === 'number' ? action.type : AutoModerationActionTypes[action.type], type: typeof action.type === 'number' ? action.type : AutoModerationActionTypes[action.type],

View File

@@ -73,6 +73,7 @@ class AutoModerationRule extends Base {
* @property {string[]} allowList The substrings that will be exempt from triggering * @property {string[]} allowList The substrings that will be exempt from triggering
* {@link AutoModerationRuleTriggerTypes.KEYWORD} and {@link AutoModerationRuleTriggerTypes.KEYWORD_PRESET} * {@link AutoModerationRuleTriggerTypes.KEYWORD} and {@link AutoModerationRuleTriggerTypes.KEYWORD_PRESET}
* @property {?number} mentionTotalLimit The total number of role & user mentions allowed per message * @property {?number} mentionTotalLimit The total number of role & user mentions allowed per message
* @property {boolean} mentionRaidProtectionEnabled Whether mention raid protection is enabled
*/ */
/** /**
@@ -85,6 +86,7 @@ class AutoModerationRule extends Base {
presets: data.trigger_metadata.presets?.map(preset => AutoModerationRuleKeywordPresetTypes[preset]) ?? [], presets: data.trigger_metadata.presets?.map(preset => AutoModerationRuleKeywordPresetTypes[preset]) ?? [],
allowList: data.trigger_metadata.allow_list ?? [], allowList: data.trigger_metadata.allow_list ?? [],
mentionTotalLimit: data.trigger_metadata.mention_total_limit ?? null, mentionTotalLimit: data.trigger_metadata.mention_total_limit ?? null,
mentionRaidProtectionEnabled: data.trigger_metadata.mention_raid_protection_enabled ?? false,
}; };
} }
@@ -236,6 +238,17 @@ class AutoModerationRule extends Base {
return this.edit({ triggerMetadata: { ...this.triggerMetadata, mentionTotalLimit }, reason }); return this.edit({ triggerMetadata: { ...this.triggerMetadata, mentionTotalLimit }, reason });
} }
/**
* Sets whether to enable mention raid protection for this auto moderation rule.
* @param {boolean} mentionRaidProtectionEnabled
* Whether to enable mention raid protection for this auto moderation rule
* @param {string} [reason] The reason for changing the mention raid protection of this auto moderation rule
* @returns {Promise<AutoModerationRule>}
*/
setMentionRaidProtectionEnabled(mentionRaidProtectionEnabled, reason) {
return this.edit({ triggerMetadata: { ...this.triggerMetadata, mentionRaidProtectionEnabled }, reason });
}
/** /**
* Sets the actions for this auto moderation rule. * Sets the actions for this auto moderation rule.
* @param {AutoModerationActionOptions[]} actions The actions of this auto moderation rule * @param {AutoModerationActionOptions[]} actions The actions of this auto moderation rule

View File

@@ -255,6 +255,7 @@ class Guild extends AnonymousGuild {
* * SEVEN_DAY_THREAD_ARCHIVE * * SEVEN_DAY_THREAD_ARCHIVE
* * PRIVATE_THREADS * * PRIVATE_THREADS
* * ROLE_ICONS * * ROLE_ICONS
* * RAID_ALERTS_DISABLED
* * ROLE_SUBSCRIPTIONS_AVAILABLE_FOR_PURCHASE * * ROLE_SUBSCRIPTIONS_AVAILABLE_FOR_PURCHASE
* * ROLE_SUBSCRIPTIONS_ENABLED * * ROLE_SUBSCRIPTIONS_ENABLED
* @typedef {string} Features * @typedef {string} Features
@@ -442,6 +443,16 @@ class Guild extends AnonymousGuild {
this.preferredLocale = data.preferred_locale; this.preferredLocale = data.preferred_locale;
} }
if ('safety_alerts_channel_id' in data) {
/**
* The safety alerts channel's id for the guild
* @type {?Snowflake}
*/
this.safetyAlertsChannelId = data.safety_alerts_channel_id;
} else {
this.safetyAlertsChannelId ??= null;
}
if (data.channels) { if (data.channels) {
this.channels.cache.clear(); this.channels.cache.clear();
for (const rawChannel of data.channels) { for (const rawChannel of data.channels) {
@@ -575,6 +586,15 @@ class Guild extends AnonymousGuild {
return this.client.channels.resolve(this.systemChannelId); return this.client.channels.resolve(this.systemChannelId);
} }
/**
* Safety alerts channel for this guild
* @type {?TextChannel}
* @readonly
*/
get safetyAlertsChannel() {
return this.client.channels.resolve(this.safetyAlertsChannelId);
}
/** /**
* Widget channel for this guild * Widget channel for this guild
* @type {?(TextChannel|NewsChannel|VoiceChannel|StageChannel|ForumChannel)} * @type {?(TextChannel|NewsChannel|VoiceChannel|StageChannel|ForumChannel)}
@@ -839,6 +859,7 @@ class Guild extends AnonymousGuild {
* @property {?TextChannelResolvable} [rulesChannel] The rules channel of the guild * @property {?TextChannelResolvable} [rulesChannel] The rules channel of the guild
* @property {?TextChannelResolvable} [publicUpdatesChannel] The community updates channel of the guild * @property {?TextChannelResolvable} [publicUpdatesChannel] The community updates channel of the guild
* @property {?string} [preferredLocale] The preferred locale of the guild * @property {?string} [preferredLocale] The preferred locale of the guild
* @property {?TextChannelResolvable} [safetyAlertsChannel] The safety alerts channel of the guild
* @property {boolean} [premiumProgressBarEnabled] Whether the guild's premium progress bar is enabled * @property {boolean} [premiumProgressBarEnabled] Whether the guild's premium progress bar is enabled
* @property {?string} [description] The discovery description of the guild * @property {?string} [description] The discovery description of the guild
* @property {Features[]} [features] The features of the guild * @property {Features[]} [features] The features of the guild
@@ -922,6 +943,9 @@ class Guild extends AnonymousGuild {
_data.description = data.description; _data.description = data.description;
} }
if (typeof data.preferredLocale !== 'undefined') _data.preferred_locale = data.preferredLocale; if (typeof data.preferredLocale !== 'undefined') _data.preferred_locale = data.preferredLocale;
if (typeof data.safetyAlertsChannel !== 'undefined') {
_data.safety_alerts_channel_id = this.client.channels.resolveId(data.safetyAlertsChannel);
}
if ('premiumProgressBarEnabled' in data) _data.premium_progress_bar_enabled = data.premiumProgressBarEnabled; if ('premiumProgressBarEnabled' in data) _data.premium_progress_bar_enabled = data.premiumProgressBarEnabled;
const newData = await this.client.api.guilds(this.id).patch({ data: _data, reason }); const newData = await this.client.api.guilds(this.id).patch({ data: _data, reason });
return this.client.actions.GuildUpdate.handle(newData).updated; return this.client.actions.GuildUpdate.handle(newData).updated;
@@ -1224,6 +1248,21 @@ class Guild extends AnonymousGuild {
return this.edit({ preferredLocale }, reason); return this.edit({ preferredLocale }, reason);
} }
/**
* Edits the safety alerts channel of the guild.
* @param {?TextChannelResolvable} safetyAlertsChannel The new safety alerts channel
* @param {string} [reason] Reason for changing the guild's safety alerts channel
* @returns {Promise<Guild>}
* @example
* // Edit the guild safety alerts channel
* guild.setSafetyAlertsChannel(channel)
* .then(updated => console.log(`Updated guild safety alerts channel to ${updated.safetyAlertsChannel.name}`))
* .catch(console.error);
*/
setSafetyAlertsChannel(safetyAlertsChannel, reason) {
return this.edit({ safetyAlertsChannel }, reason);
}
/** /**
* Edits the enabled state of the guild's premium progress bar * Edits the enabled state of the guild's premium progress bar
* @param {boolean} [enabled=true] The new enabled state of the guild's premium progress bar * @param {boolean} [enabled=true] The new enabled state of the guild's premium progress bar

10
typings/index.d.ts vendored
View File

@@ -1013,6 +1013,8 @@ export class Guild extends AnonymousGuild {
public roles: RoleManager; public roles: RoleManager;
public readonly rulesChannel: TextChannel | null; public readonly rulesChannel: TextChannel | null;
public rulesChannelId: Snowflake | null; public rulesChannelId: Snowflake | null;
public readonly safetyAlertsChannel: TextChannel | null;
public safetyAlertsChannelId: Snowflake | null;
public scheduledEvents: GuildScheduledEventManager; public scheduledEvents: GuildScheduledEventManager;
public readonly shard: WebSocketShard; public readonly shard: WebSocketShard;
public shardId: number; public shardId: number;
@@ -1073,6 +1075,7 @@ export class Guild extends AnonymousGuild {
/** @deprecated Use {@link RoleManager.setPositions} instead */ /** @deprecated Use {@link RoleManager.setPositions} instead */
public setRolePositions(rolePositions: readonly RolePosition[]): Promise<Guild>; public setRolePositions(rolePositions: readonly RolePosition[]): Promise<Guild>;
public setRulesChannel(rulesChannel: TextChannelResolvable | null, reason?: string): Promise<Guild>; public setRulesChannel(rulesChannel: TextChannelResolvable | null, reason?: string): Promise<Guild>;
public setSafetyAlertsChannel(safetyAlertsChannel: TextChannelResolvable | null, reason?: string): Promise<Guild>;
public setSplash(splash: BufferResolvable | Base64Resolvable | null, reason?: string): Promise<Guild>; public setSplash(splash: BufferResolvable | Base64Resolvable | null, reason?: string): Promise<Guild>;
public setSystemChannel(systemChannel: TextChannelResolvable | null, reason?: string): Promise<Guild>; public setSystemChannel(systemChannel: TextChannelResolvable | null, reason?: string): Promise<Guild>;
public setSystemChannelFlags(systemChannelFlags: SystemChannelFlagsResolvable, reason?: string): Promise<Guild>; public setSystemChannelFlags(systemChannelFlags: SystemChannelFlagsResolvable, reason?: string): Promise<Guild>;
@@ -4227,6 +4230,10 @@ export class AutoModerationRule extends Base {
public setRegexPatterns(regexPatterns: string[], reason?: string): Promise<AutoModerationRule>; public setRegexPatterns(regexPatterns: string[], reason?: string): Promise<AutoModerationRule>;
public setPresets(presets: AutoModerationRuleKeywordPresetType[], reason?: string): Promise<AutoModerationRule>; public setPresets(presets: AutoModerationRuleKeywordPresetType[], reason?: string): Promise<AutoModerationRule>;
public setAllowList(allowList: string[], reason?: string): Promise<AutoModerationRule>; public setAllowList(allowList: string[], reason?: string): Promise<AutoModerationRule>;
public setMentionRaidProtectionEnabled(
mentionRaidProtectionEnabled: boolean,
reason?: string,
): Promise<AutoModerationRule>;
public setMentionTotalLimit(mentionTotalLimit: number, reason?: string): Promise<AutoModerationRule>; public setMentionTotalLimit(mentionTotalLimit: number, reason?: string): Promise<AutoModerationRule>;
public setActions(actions: AutoModerationActionOptions[], reason?: string): Promise<AutoModerationRule>; public setActions(actions: AutoModerationActionOptions[], reason?: string): Promise<AutoModerationRule>;
public setEnabled(enabled?: boolean, reason?: string): Promise<AutoModerationRule>; public setEnabled(enabled?: boolean, reason?: string): Promise<AutoModerationRule>;
@@ -4315,6 +4322,7 @@ export interface AutoModerationTriggerMetadata {
regexPatterns: string[]; regexPatterns: string[];
presets: (AutoModerationRuleKeywordPresetType | AutoModerationRuleKeywordPresetTypes)[]; presets: (AutoModerationRuleKeywordPresetType | AutoModerationRuleKeywordPresetTypes)[];
allowList: string[]; allowList: string[];
mentionRaidProtectionEnabled: boolean;
mentionTotalLimit: number | null; mentionTotalLimit: number | null;
} }
@@ -5419,6 +5427,7 @@ export interface GuildEditData {
rulesChannel?: TextChannelResolvable | null; rulesChannel?: TextChannelResolvable | null;
publicUpdatesChannel?: TextChannelResolvable | null; publicUpdatesChannel?: TextChannelResolvable | null;
preferredLocale?: string | null; preferredLocale?: string | null;
safetyAlertsChannel?: TextChannelResolvable | null;
premiumProgressBarEnabled?: boolean; premiumProgressBarEnabled?: boolean;
description?: string | null; description?: string | null;
features?: GuildFeatures[]; features?: GuildFeatures[];
@@ -5471,6 +5480,7 @@ export type GuildFeatures =
| 'SEVEN_DAY_THREAD_ARCHIVE' | 'SEVEN_DAY_THREAD_ARCHIVE'
| 'PRIVATE_THREADS' | 'PRIVATE_THREADS'
| 'ROLE_ICONS' | 'ROLE_ICONS'
| 'RAID_ALERTS_DISABLED'
| 'ROLE_SUBSCRIPTIONS_AVAILABLE_FOR_PURCHASE' | 'ROLE_SUBSCRIPTIONS_AVAILABLE_FOR_PURCHASE'
| 'ROLE_SUBSCRIPTIONS_ENABLED'; | 'ROLE_SUBSCRIPTIONS_ENABLED';

View File

@@ -11,7 +11,6 @@ import {
APIChannel, APIChannel,
APIEmoji, APIEmoji,
APIExtendedInvite, APIExtendedInvite,
APIGuild,
APIGuildIntegration, APIGuildIntegration,
APIGuildIntegrationApplication, APIGuildIntegrationApplication,
APIGuildMember, APIGuildMember,
@@ -79,6 +78,16 @@ import {
APITextInputComponent, APITextInputComponent,
APIModalActionRowComponent, APIModalActionRowComponent,
APIModalSubmitInteraction, APIModalSubmitInteraction,
Permissions,
GuildDefaultMessageNotifications,
GuildExplicitContentFilter,
GuildMFALevel,
GuildSystemChannelFlags,
GuildPremiumTier,
GuildNSFWLevel,
GuildHubType,
GuildVerificationLevel,
GuildFeature,
LocalizationMap LocalizationMap
} from 'discord-api-types/v9'; } from 'discord-api-types/v9';
import { GuildChannel, Guild, PermissionOverwrites, InteractionType } from '.'; import { GuildChannel, Guild, PermissionOverwrites, InteractionType } from '.';
@@ -282,6 +291,50 @@ export interface APIAutoModerationRuleTriggerMetadata {
allow_list?: string[]; allow_list?: string[];
regex_patterns?: string[]; regex_patterns?: string[];
mention_total_limit?: number; mention_total_limit?: number;
mention_raid_protection_enabled?: boolean;
}
export interface APIGuild extends APIPartialGuild {
icon_hash?: string | null;
discovery_splash: string | null;
owner?: boolean;
owner_id: Snowflake;
permissions?: Permissions;
region: string;
afk_channel_id: Snowflake | null;
afk_timeout: number;
widget_enabled?: boolean;
widget_channel_id?: Snowflake | null;
verification_level: GuildVerificationLevel;
default_message_notifications: GuildDefaultMessageNotifications;
explicit_content_filter: GuildExplicitContentFilter;
roles: APIRole[];
emojis: APIEmoji[];
features: GuildFeature[];
mfa_level: GuildMFALevel;
application_id: Snowflake | null;
system_channel_id: Snowflake | null;
system_channel_flags: GuildSystemChannelFlags;
rules_channel_id: Snowflake | null;
max_presences?: number | null;
max_members?: number;
vanity_url_code: string | null;
description: string | null;
banner: string | null;
premium_tier: GuildPremiumTier;
premium_subscription_count?: number;
preferred_locale: string;
public_updates_channel_id: Snowflake | null;
max_video_channel_users?: number;
approximate_member_count?: number;
approximate_presence_count?: number;
welcome_screen?: APIGuildWelcomeScreen;
nsfw_level: GuildNSFWLevel;
stickers: APISticker[];
premium_progress_bar_enabled: boolean;
hub_type: GuildHubType | null;
safety_alerts_channel_id: Snowflake | null;
} }
export interface APIApplicationRoleConnectionMetadata { export interface APIApplicationRoleConnectionMetadata {