From a749905740664a4ae63bdf0837641f3e8a148874 Mon Sep 17 00:00:00 2001 From: Fleny Date: Mon, 7 Oct 2024 06:37:17 +0200 Subject: [PATCH] update DiscordAuditLogChange to be less manual (#3823) --- .../bot/src/transformers/auditLogEntry.ts | 129 ++----------- .../src/transformers/reverse/auditLogEntry.ts | 144 ++------------ packages/bot/src/transformers/types.ts | 94 ++-------- packages/types/src/discord.ts | 177 ++++++++---------- 4 files changed, 107 insertions(+), 437 deletions(-) diff --git a/packages/bot/src/transformers/auditLogEntry.ts b/packages/bot/src/transformers/auditLogEntry.ts index eb880529c..0a66c9fd3 100644 --- a/packages/bot/src/transformers/auditLogEntry.ts +++ b/packages/bot/src/transformers/auditLogEntry.ts @@ -1,133 +1,26 @@ import type { DiscordAuditLogEntry } from '@discordeno/types' -import { type AuditLogEntry, type Bot, iconHashToBigInt } from '../index.js' +import { type AuditLogEntry, type Bot } from '../index.js' export function transformAuditLogEntry(bot: Bot, payload: DiscordAuditLogEntry): AuditLogEntry { const auditLogEntry = { id: bot.transformers.snowflake(payload.id), - changes: payload.changes?.map((change) => { - switch (change.key) { - case '$add': - case '$remove': - return { - key: change.key, - new: change.new_value?.map((val) => ({ - id: val.id ? bot.transformers.snowflake(val.id) : undefined, - name: val.name, - })), - old: change.old_value?.map((val) => ({ - id: val?.id ? bot.transformers.snowflake(val.id) : undefined, - name: val?.name, - })), - } - case 'rules_channel_id': - case 'public_updates_channel_id': - case 'owner_id': - case 'widget_channel_id': - case 'system_channel_id': - case 'application_id': - case 'permissions': - case 'allow': - case 'deny': - case 'channel_id': - case 'inviter_id': - case 'id': - return { - key: change.key, - old: change.old_value ? bot.transformers.snowflake(change.old_value) : undefined, - new: change.new_value ? bot.transformers.snowflake(change.new_value) : undefined, - } - case 'discovery_splash_hash': - case 'banner_hash': - case 'icon_hash': - case 'image_hash': - case 'splash_hash': - case 'avatar_hash': - return { - key: change.key, - old: change.old_value ? iconHashToBigInt(change.old_value) : undefined, - new: change.new_value ? iconHashToBigInt(change.new_value) : undefined, - } - case 'name': - case 'description': - case 'preferred_locale': - case 'region': - case 'afk_channel_id': - case 'vanity_url_code': - case 'topic': - case 'code': - case 'nick': - case 'location': - return { - key: change.key, - old: change.old_value, - new: change.new_value, - } - case 'afk_timeout': - case 'mfa_level': - case 'verification_level': - case 'explicit_content_filter': - case 'default_message_notifications': - case 'prune_delete_days': - case 'position': - case 'bitrate': - case 'rate_limit_per_user': - case 'color': - case 'max_uses': - case 'uses': - case 'max_age': - case 'expire_behavior': - case 'expire_grace_period': - case 'user_limit': - case 'privacy_level': - case 'entity_type': - case 'status': - return { - key: change.key, - old: change.old_value ? Number(change.old_value) : undefined, - new: change.new_value ? Number(change.new_value) : undefined, - } - case 'widget_enabled': - case 'nsfw': - case 'hoist': - case 'mentionable': - case 'temporary': - case 'deaf': - case 'mute': - case 'enable_emoticons': - return { - key: change.key, - old: change.old_value ?? false, - new: change.new_value ?? false, - } - case 'permission_overwrites': - return { - key: change.key, - old: change.old_value, - new: change.new_value, - } - default: - return { - key: change.key, - old: change.old_value, - new: change.new_value, - } - } - }), + changes: payload.changes, userId: payload.user_id ? bot.transformers.snowflake(payload.user_id) : undefined, targetId: payload.target_id ? bot.transformers.snowflake(payload.target_id) : undefined, actionType: payload.action_type, options: payload.options ? { - deleteMemberDays: payload.options.delete_member_days ? Number(payload.options.delete_member_days) : 0, - membersRemoved: payload.options.members_removed ? Number(payload.options.members_removed) : 0, - channelId: payload.options.channel_id ? bot.transformers.snowflake(payload.options.channel_id) : undefined, - messageId: payload.options.message_id ? bot.transformers.snowflake(payload.options.message_id) : undefined, - count: payload.options.count ? Number(payload.options.count) : 0, - id: payload.options.id ? bot.transformers.snowflake(payload.options.id) : undefined, - type: Number(payload.options.type), - roleName: payload.options.role_name, + applicationId: payload.options.application_id ? bot.transformers.snowflake(payload.options.application_id) : undefined, autoModerationRuleName: payload.options.auto_moderation_rule_name, autoModerationRuleTriggerType: payload.options.auto_moderation_rule_trigger_type, + channelId: payload.options.channel_id ? bot.transformers.snowflake(payload.options.channel_id) : undefined, + count: payload.options.count ? Number(payload.options.count) : undefined, + deleteMemberDays: payload.options.delete_member_days ? Number(payload.options.delete_member_days) : undefined, + id: payload.options.id ? bot.transformers.snowflake(payload.options.id) : undefined, + membersRemoved: payload.options.members_removed ? Number(payload.options.members_removed) : undefined, + messageId: payload.options.message_id ? bot.transformers.snowflake(payload.options.message_id) : undefined, + roleName: payload.options.role_name, + type: payload.options.type ? Number(payload.options.type) : undefined, integrationType: payload.options.integration_type, } : undefined, diff --git a/packages/bot/src/transformers/reverse/auditLogEntry.ts b/packages/bot/src/transformers/reverse/auditLogEntry.ts index 269ab2127..66f00a50c 100644 --- a/packages/bot/src/transformers/reverse/auditLogEntry.ts +++ b/packages/bot/src/transformers/reverse/auditLogEntry.ts @@ -1,131 +1,10 @@ import type { DiscordAuditLogEntry } from '@discordeno/types' -import { type AuditLogEntry, type Bot, iconBigintToHash } from '../../index.js' +import { type AuditLogEntry, type Bot } from '../../index.js' export function transformAuditLogEntryToDiscordAuditLogEntry(bot: Bot, payload: AuditLogEntry): DiscordAuditLogEntry { return { id: bot.transformers.reverse.snowflake(payload.id), - // @ts-expect-error: ts can't identify return type of switch case - changes: payload.changes?.map((change) => { - switch (change.key) { - case '$add': - case '$remove': - return { - key: change.key, - new_value: ( - change.new as Array<{ - id: bigint | undefined - name: string | undefined - }> - )?.map((val) => ({ - id: val.id ? bot.transformers.reverse.snowflake(val.id) : undefined, - name: val.name, - })), - old_value: ( - change.old as - | Array<{ - id: bigint | undefined - name: string | undefined - }> - | undefined - )?.map((val) => ({ - id: val?.id ? bot.transformers.reverse.snowflake(val.id) : undefined, - name: val?.name, - })), - } - case 'rules_channel_id': - case 'public_updates_channel_id': - case 'owner_id': - case 'widget_channel_id': - case 'system_channel_id': - case 'application_id': - case 'permissions': - case 'allow': - case 'deny': - case 'channel_id': - case 'inviter_id': - case 'id': - return { - key: change.key, - old_value: change.old ? bot.transformers.reverse.snowflake(change.old as bigint) : '', - new_value: change.new ? bot.transformers.reverse.snowflake(change.new as bigint) : '', - } - case 'discovery_splash_hash': - case 'banner_hash': - case 'icon_hash': - case 'image_hash': - case 'splash_hash': - case 'avatar_hash': - return { - key: change.key, - old_value: change.old ? iconBigintToHash(change.old as bigint) : '', - new_value: change.new ? iconBigintToHash(change.new as bigint) : '', - } - case 'name': - case 'description': - case 'preferred_locale': - case 'region': - case 'afk_channel_id': - case 'vanity_url_code': - case 'topic': - case 'code': - case 'nick': - case 'location': - return { - key: change.key, - old_value: change.old, - new_value: change.new, - } - case 'afk_timeout': - case 'mfa_level': - case 'verification_level': - case 'explicit_content_filter': - case 'default_message_notifications': - case 'prune_delete_days': - case 'position': - case 'bitrate': - case 'rate_limit_per_user': - case 'color': - case 'max_uses': - case 'uses': - case 'max_age': - case 'expire_behavior': - case 'expire_grace_period': - case 'user_limit': - case 'privacy_level': - case 'entity_type': - case 'status': - return { - key: change.key, - old_value: change.old ? Number(change.old) : '', - new_value: change.new ? Number(change.new) : '', - } - case 'widget_enabled': - case 'nsfw': - case 'hoist': - case 'mentionable': - case 'temporary': - case 'deaf': - case 'mute': - case 'enable_emoticons': - return { - key: change.key, - old_value: change.old, - new_value: change.new, - } - case 'permission_overwrites': - return { - key: change.key, - old_value: change.old, - new_value: change.new, - } - default: - return { - key: change.key, - old_value: change.old, - new_value: change.new, - } - } - }), + changes: payload.changes, user_id: payload.userId ? bot.transformers.reverse.snowflake(payload.userId) : null, target_id: payload.targetId ? bot.transformers.reverse.snowflake(payload.targetId) : null, action_type: payload.actionType, @@ -133,18 +12,17 @@ export function transformAuditLogEntryToDiscordAuditLogEntry(bot: Bot, payload: options: payload.options ? { // respect transformer as reference than type - delete_member_days: payload.options.deleteMemberDays === 0 ? payload.options.deleteMemberDays.toString() : '', - members_removed: payload.options.membersRemoved === 0 ? payload.options.membersRemoved.toString() : '', - channel_id: payload.options.channelId ? bot.transformers.reverse.snowflake(payload.options.channelId) : '', - message_id: payload.options.messageId ? bot.transformers.reverse.snowflake(payload.options.messageId) : '', - count: payload.options.count === 0 ? payload.options.count.toString() : '', - id: payload.options.id ? bot.transformers.reverse.snowflake(payload.options.id) : '', - type: payload.options.type.toString(), - role_name: payload.options.roleName, - // make up value to make ts shut up, the orginal value do not persevere in transformer - application_id: '', + application_id: payload.options.applicationId ? bot.transformers.reverse.snowflake(payload.options.applicationId) : undefined, auto_moderation_rule_name: payload.options.autoModerationRuleName, auto_moderation_rule_trigger_type: payload.options.autoModerationRuleTriggerType, + channel_id: payload.options.channelId ? bot.transformers.reverse.snowflake(payload.options.channelId) : undefined, + count: payload.options.count !== undefined ? payload.options.count.toString() : undefined, + delete_member_days: payload.options.deleteMemberDays !== undefined ? payload.options.deleteMemberDays.toString() : undefined, + id: payload.options.id ? bot.transformers.reverse.snowflake(payload.options.id) : undefined, + members_removed: payload.options.membersRemoved !== undefined ? payload.options.membersRemoved.toString() : undefined, + message_id: payload.options.messageId ? bot.transformers.reverse.snowflake(payload.options.messageId) : undefined, + role_name: payload.options.roleName, + type: payload.options.type !== undefined ? payload.options.type.toString() : undefined, integration_type: payload.options.integrationType, } : undefined, diff --git a/packages/bot/src/transformers/types.ts b/packages/bot/src/transformers/types.ts index 61879755e..704e8e73d 100644 --- a/packages/bot/src/transformers/types.ts +++ b/packages/bot/src/transformers/types.ts @@ -15,6 +15,7 @@ import type { DefaultMessageNotificationLevels, DiscordActivityLocationKind, DiscordApplicationIntegrationType, + DiscordAuditLogChange, DiscordAutoModerationRuleTriggerMetadataPresets, DiscordEntitlementType, DiscordGuildOnboardingMode, @@ -288,96 +289,25 @@ export interface AuditLogEntry { id: bigint userId?: bigint reason?: string - changes?: AuditLogChange[] + changes?: DiscordAuditLogChange[] targetId?: bigint actionType: AuditLogEvents options?: OptionalAuditEntryInfo } -export interface AuditLogChange { - new?: string | number | bigint | boolean | DiscordOverwrite[] | Partial[] - old?: string | number | bigint | boolean | DiscordOverwrite[] | Partial[] - key: - | 'id' - | 'name' - | 'description' - | 'type' - | 'permissions' - | 'locked' - | 'invitable' - | 'nsfw' - | 'archived' - | 'position' - | 'topic' - | 'bitrate' - | 'default_auto_archive_duration' - | 'auto_archive_duration' - | 'allow' - | 'deny' - | 'channel_id' - | 'deaf' - | 'mute' - | 'status' - | 'nick' - | 'communication_disabled_until' - | 'color' - | 'permission_overwrites' - | 'user_limit' - | 'rate_limit_per_user' - | 'owner_id' - | 'application_id' - | 'hoist' - | 'mentionable' - | 'location' - | 'verification_level' - | 'default_message_notifications' - | 'explicit_content_filter' - | 'preferred_locale' - | 'afk_timeout' - | 'afk_channel_id' - | 'system_channel_id' - | 'widget_enabled' - | 'mfa_level' - | 'vanity_url_code' - | 'icon_hash' - | 'widget_channel_id' - | 'rules_channel_id' - | 'public_updates_channel_id' - | 'code' - | 'region' - | 'privacy_level' - | 'entity_type' - | 'enable_emoticons' - | 'expire_behavior' - | 'expire_grace_period' - | 'uses' - | 'max_uses' - | 'max_age' - | 'temporary' - | 'discovery_splash_hash' - | 'banner_hash' - | 'image_hash' - | 'splash_hash' - | 'inviter_id' - | 'avatar_hash' - | 'command_id' - | 'prune_delete_days' - | '$add' - | '$remove' -} - export interface OptionalAuditEntryInfo { - id?: bigint + applicationId?: bigint + autoModerationRuleName?: string + autoModerationRuleTriggerType?: string channelId?: bigint + count?: number + deleteMemberDays?: number + id?: bigint + membersRemoved?: number messageId?: bigint - type: number - count: number - deleteMemberDays: number - membersRemoved: number - roleName: string - autoModerationRuleName: string - autoModerationRuleTriggerType: string - integrationType: string + roleName?: string + type?: number + integrationType?: string } export interface AutoModerationActionExecution { diff --git a/packages/types/src/discord.ts b/packages/types/src/discord.ts index 49cd32719..889129e5c 100644 --- a/packages/types/src/discord.ts +++ b/packages/types/src/discord.ts @@ -2184,100 +2184,69 @@ export interface DiscordAuditLogEntry { reason?: string } +export type DiscordAuditLogChangeObject = { + [K in keyof T]: { + new_value?: T[K] + old_value?: T[K] + key: K + } +}[keyof T] + +// Done manually as it is clearer in this way +/** Partial role audit log entry change exception */ +export type DiscordAuditLogChangePartialRole = { new_value: { id: string; name: string }[]; key: '$add' | '$remove' } + +/** + * Invite audit log entry change exception + * + * @remarks + * While the docs say that 'channel.id' will never exist, we keep it as it is very complex to remove, the user should not use it and use the provided 'channel_id' value instead + */ +export type DiscordAuditLogChangeInvite = DiscordAuditLogChangeObject | DiscordAuditLogChangeObject<{ channel_id: string }> + +/** + * Invite Metadata audit log entry change exception + * + * @remarks + * While the docs say that 'channel.id' will never exist, we keep it as it is very complex to remove, the user should not use it and use the provided 'channel_id' value instead + */ +export type DiscordAuditLogChangeInviteMetadata = + | DiscordAuditLogChangeObject + | DiscordAuditLogChangeObject<{ channel_id: string }> + +/** Webhook audit log entry change exception */ +export type DiscordAuditLogChangeWebhook = + | DiscordAuditLogChangeObject> + | DiscordAuditLogChangeObject<{ avatar_hash: DiscordWebhook['avatar'] }> + +// Done manually as it is clearer in this way +/** Command Permission audit log entry change exception */ +export type DiscordAuditLogChangeApplicationCommandPermissions = { + new_value?: DiscordApplicationCommandPermissions + old_value?: DiscordApplicationCommandPermissions + key: `${number}` +} + /** https://discord.com/developers/docs/resources/audit-log#audit-log-change-object-audit-log-change-structure */ export type DiscordAuditLogChange = - | { - new_value: string - old_value: string - key: - | 'name' - | 'description' - | 'discovery_splash_hash' - | 'banner_hash' - | 'preferred_locale' - | 'rules_channel_id' - | 'public_updates_channel_id' - | 'icon_hash' - | 'image_hash' - | 'splash_hash' - | 'owner_id' - | 'region' - | 'afk_channel_id' - | 'vanity_url_code' - | 'widget_channel_id' - | 'system_channel_id' - | 'topic' - | 'application_id' - | 'permissions' - | 'allow' - | 'deny' - | 'code' - | 'channel_id' - | 'inviter_id' - | 'nick' - | 'avatar_hash' - | 'id' - | 'location' - | 'command_id' - } - | { - new_value: number - old_value: number - key: - | 'afk_timeout' - | 'mfa_level' - | 'verification_level' - | 'explicit_content_filter' - | 'default_message_notifications' - | 'prune_delete_days' - | 'position' - | 'bitrate' - | 'rate_limit_per_user' - | 'color' - | 'max_uses' - | 'uses' - | 'max_age' - | 'expire_behavior' - | 'expire_grace_period' - | 'user_limit' - | 'privacy_level' - | 'auto_archive_duration' - | 'default_auto_archive_duration' - | 'entity_type' - | 'status' - | 'communication_disabled_until' - } - | { - new_value: Partial[] - old_value?: Partial[] - key: '$add' | '$remove' - } - | { - new_value: boolean - old_value: boolean - key: - | 'widget_enabled' - | 'nsfw' - | 'hoist' - | 'mentionable' - | 'temporary' - | 'deaf' - | 'mute' - | 'enable_emoticons' - | 'archived' - | 'locked' - | 'invitable' - } - | { - new_value: DiscordOverwrite[] - old_value: DiscordOverwrite[] - key: 'permission_overwrites' - } - | { - new_value: string | number - old_value: string | number - key: 'type' - } + | DiscordAuditLogChangeObject + | DiscordAuditLogChangeObject + | DiscordAuditLogChangeObject + | DiscordAuditLogChangeObject + | DiscordAuditLogChangePartialRole + | DiscordAuditLogChangeObject + | DiscordAuditLogChangeInvite + | DiscordAuditLogChangeInviteMetadata + | DiscordAuditLogChangeWebhook + | DiscordAuditLogChangeObject + | DiscordAuditLogChangeObject + | DiscordAuditLogChangeObject + | DiscordAuditLogChangeObject + | DiscordAuditLogChangeObject + | DiscordAuditLogChangeApplicationCommandPermissions + | DiscordAuditLogChangeObject + | DiscordAuditLogChangeObject + | DiscordAuditLogChangeObject /** https://discord.com/developers/docs/resources/audit-log#audit-log-entry-object-optional-audit-entry-info */ export interface DiscordOptionalAuditEntryInfo { @@ -2286,73 +2255,73 @@ export interface DiscordOptionalAuditEntryInfo { * * Event types: `APPLICATION_COMMAND_PERMISSION_UPDATE` */ - application_id: string + application_id?: string /** * Name of the Auto Moderation rule that was triggered. * * Event types: `AUTO_MODERATION_BLOCK_MESSAGE`, `AUTO_MODERATION_FLAG_TO_CHANNEL`, `AUTO_MODERATION_USER_COMMUNICATION_DISABLED` */ - auto_moderation_rule_name: string + auto_moderation_rule_name?: string /** * Trigger type of the Auto Moderation rule that was triggered. * * Event types: `AUTO_MODERATION_BLOCK_MESSAGE`, `AUTO_MODERATION_FLAG_TO_CHANNEL`, `AUTO_MODERATION_USER_COMMUNICATION_DISABLED` */ - auto_moderation_rule_trigger_type: string + auto_moderation_rule_trigger_type?: string /** * Channel in which the entities were targeted. * * Event types: `MEMBER_MOVE`, `MESSAGE_PIN`, `MESSAGE_UNPIN`, `MESSAGE_DELETE`, `STAGE_INSTANCE_CREATE`, `STAGE_INSTANCE_UPDATE`, `STAGE_INSTANCE_DELETE` */ - channel_id: string + channel_id?: string /** * Number of entities that were targeted. * * Event types: `MESSAGE_DELETE`, `MESSAGE_BULK_DELETE`, `MEMBER_DISCONNECT`, `MEMBER_MOVE` */ - count: string + count?: string /** * Number of days after which inactive members were kicked. * * Event types: `MEMBER_PRUNE` */ - delete_member_days: string + delete_member_days?: string /** * ID of the overwritten entity. * * Event types: `CHANNEL_OVERWRITE_CREATE`, `CHANNEL_OVERWRITE_UPDATE`, `CHANNEL_OVERWRITE_DELETE` */ - id: string + id?: string /** * Number of members removed by the prune. * * Event types: `MEMBER_PRUNE` */ - members_removed: string + members_removed?: string /** * ID of the message that was targeted. * * Event types: `MESSAGE_PIN`, `MESSAGE_UNPIN`, `STAGE_INSTANCE_CREATE`, `STAGE_INSTANCE_UPDATE`, `STAGE_INSTANCE_DELETE` */ - message_id: string + message_id?: string /** * Name of the role if type is "0" (not present if type is "1"). * * Event types: `CHANNEL_OVERWRITE_CREATE`, `CHANNEL_OVERWRITE_UPDATE`, `CHANNEL_OVERWRITE_DELETE` */ - role_name: string + role_name?: string /** * Type of overwritten entity - "0", for "role", or "1" for "member". * * Event types: `CHANNEL_OVERWRITE_CREATE`, `CHANNEL_OVERWRITE_UPDATE`, `CHANNEL_OVERWRITE_DELETE` */ - type: string + type?: string /** * The type of integration which performed the action * * Event types: `MEMBER_KICK`, `MEMBER_ROLE_UPDATE` */ - integration_type: string + integration_type?: string } export interface DiscordScheduledEvent {