From b7db305deea05ca85b62fbfc7e8b284e163c9b9a Mon Sep 17 00:00:00 2001 From: Fleny Date: Tue, 26 Aug 2025 19:56:43 +0200 Subject: [PATCH] refactor: Use TransformerFunction to define transformers (#4402) Co-authored-by: Link --- packages/bot/src/transformers.ts | 258 +++++++++++++++---------------- 1 file changed, 128 insertions(+), 130 deletions(-) diff --git a/packages/bot/src/transformers.ts b/packages/bot/src/transformers.ts index cd759b4f7..558ffca0e 100644 --- a/packages/bot/src/transformers.ts +++ b/packages/bot/src/transformers.ts @@ -84,6 +84,7 @@ import { type DesiredPropertiesBehavior, type SetupDesiredProps, type TransformersDesiredProperties, + type TransformersObjects, type TransformProperty, } from './desiredProperties.js' import { transformIncidentsData } from './transformers/incidentsData.js' @@ -488,137 +489,113 @@ export type Transformers, payload: UnfurledMediaItem) => DiscordUnfurledMediaItem user: (bot: Bot, payload: SetupDesiredProps) => DiscordUser } - activity: (bot: Bot, payload: DiscordActivity) => Activity - activityInstance: (bot: Bot, payload: DiscordActivityInstance) => SetupDesiredProps - activityLocation: (bot: Bot, payload: DiscordActivityLocation) => SetupDesiredProps - application: (bot: Bot, payload: DiscordApplication, extra?: { shardId?: number }) => Application - applicationCommand: (bot: Bot, payload: DiscordApplicationCommand) => ApplicationCommand - applicationCommandOption: (bot: Bot, payload: DiscordApplicationCommandOption) => ApplicationCommandOption - applicationCommandOptionChoice: (bot: Bot, payload: DiscordApplicationCommandOptionChoice) => ApplicationCommandOptionChoice - applicationCommandPermission: ( - bot: Bot, - payload: DiscordGuildApplicationCommandPermissions, - ) => GuildApplicationCommandPermissions - attachment: (bot: Bot, payload: DiscordAttachment) => SetupDesiredProps - auditLogEntry: (bot: Bot, payload: DiscordAuditLogEntry) => AuditLogEntry - automodActionExecution: (bot: Bot, payload: DiscordAutoModerationActionExecution) => AutoModerationActionExecution - automodRule: (bot: Bot, payload: DiscordAutoModerationRule) => AutoModerationRule - avatarDecorationData: ( - bot: Bot, - payload: DiscordAvatarDecorationData, - ) => SetupDesiredProps - channel: (bot: Bot, payload: DiscordChannel, extra?: { guildId?: BigString }) => SetupDesiredProps - collectibles: (bot: Bot, payload: DiscordCollectibles) => SetupDesiredProps - component: (bot: Bot, payload: DiscordMessageComponent) => Component - defaultReactionEmoji: ( - bot: Bot, - payload: DiscordDefaultReactionEmoji, - ) => SetupDesiredProps - embed: (bot: Bot, payload: DiscordEmbed) => Embed - emoji: (bot: Bot, payload: DiscordEmoji) => SetupDesiredProps - entitlement: (bot: Bot, payload: DiscordEntitlement) => SetupDesiredProps - forumTag: (bot: Bot, payload: DiscordForumTag) => SetupDesiredProps - gatewayBot: (bot: Bot, payload: DiscordGetGatewayBot) => GetGatewayBot - guild: (bot: Bot, payload: DiscordGuild, extra?: { shardId?: number }) => SetupDesiredProps - guildOnboarding: (bot: Bot, payload: DiscordGuildOnboarding) => SetupDesiredProps - guildOnboardingPrompt: ( - bot: Bot, - payload: DiscordGuildOnboardingPrompt, - ) => SetupDesiredProps - guildOnboardingPromptOption: (bot: Bot, payload: DiscordGuildOnboardingPromptOption) => GuildOnboardingPromptOption - incidentsData: (bot: Bot, payload: DiscordIncidentsData) => IncidentsData - integration: (bot: Bot, payload: DiscordIntegrationCreateUpdate) => Integration - interaction: ( - bot: Bot, - payload: DiscordInteraction, - extra?: { shardId?: number }, - ) => SetupDesiredProps - interactionCallback: (bot: Bot, payload: DiscordInteractionCallback) => SetupDesiredProps - interactionCallbackResponse: ( - bot: Bot, - payload: DiscordInteractionCallbackResponse, - extra?: { shardId?: number }, - ) => SetupDesiredProps - interactionDataOptions: (bot: Bot, payload: DiscordInteractionDataOption) => InteractionDataOption - interactionDataResolved: ( - bot: Bot, - payload: DiscordInteractionDataResolved, - extra?: { shardId?: number; guildId?: BigString }, - ) => TransformProperty - interactionResource: ( - bot: Bot, - payload: DiscordInteractionResource, - extra?: { shardId?: number }, - ) => SetupDesiredProps - invite: ( - bot: Bot, - payload: DiscordInviteCreate | DiscordInviteMetadata, - extra?: { shardId?: number }, - ) => SetupDesiredProps - inviteStageInstance: ( - bot: Bot, - payload: DiscordInviteStageInstance, - extra?: { guildId: BigString }, - ) => SetupDesiredProps - lobby: (bot: Bot, payload: DiscordLobby) => SetupDesiredProps - lobbyMember: (bot: Bot, payload: DiscordLobbyMember) => SetupDesiredProps - mediaGalleryItem: (bot: Bot, payload: DiscordMediaGalleryItem) => MediaGalleryItem - member: ( - bot: Bot, - payload: DiscordMember, - extra?: { guildId?: BigString; userId?: BigString }, - ) => SetupDesiredProps - message: (bot: Bot, payload: DiscordMessage, extra?: { shardId?: number }) => SetupDesiredProps - messageCall: (bot: Bot, payload: DiscordMessageCall) => SetupDesiredProps - messageInteractionMetadata: ( - bot: Bot, - payload: DiscordMessageInteractionMetadata, - ) => SetupDesiredProps - messagePin: ( - bot: Bot, - payload: DiscordMessagePin, - extra?: { shardId?: number }, - ) => SetupDesiredProps - messageSnapshot: ( - bot: Bot, - payload: DiscordMessageSnapshot, - extra?: { shardId?: number }, - ) => SetupDesiredProps - nameplate: (bot: Bot, payload: DiscordNameplate) => SetupDesiredProps - poll: (bot: Bot, payload: DiscordPoll) => SetupDesiredProps - pollMedia: (bot: Bot, payload: DiscordPollMedia) => SetupDesiredProps - presence: (bot: Bot, payload: DiscordPresenceUpdate) => PresenceUpdate - role: (bot: Bot, payload: DiscordRole, extra?: { guildId?: BigString }) => SetupDesiredProps - roleColors: (bot: Bot, payload: DiscordRoleColors) => SetupDesiredProps - scheduledEvent: (bot: Bot, payload: DiscordScheduledEvent) => SetupDesiredProps - scheduledEventRecurrenceRule: ( - bot: Bot, - payload: DiscordScheduledEventRecurrenceRule, - ) => SetupDesiredProps - sku: (bot: Bot, payload: DiscordSku) => SetupDesiredProps - soundboardSound: (bot: Bot, payload: DiscordSoundboardSound) => SetupDesiredProps + activity: TransformerFunction + activityInstance: TransformerFunction + activityLocation: TransformerFunction + application: TransformerFunction + applicationCommand: TransformerFunction + applicationCommandOption: TransformerFunction + applicationCommandOptionChoice: TransformerFunction< + TProps, + TBehavior, + DiscordApplicationCommandOptionChoice, + ApplicationCommandOptionChoice, + {}, + 'unchanged' + > + applicationCommandPermission: TransformerFunction< + TProps, + TBehavior, + DiscordGuildApplicationCommandPermissions, + GuildApplicationCommandPermissions, + {}, + 'unchanged' + > + attachment: TransformerFunction + auditLogEntry: TransformerFunction + automodActionExecution: TransformerFunction + automodRule: TransformerFunction + avatarDecorationData: TransformerFunction + channel: TransformerFunction + collectibles: TransformerFunction + component: TransformerFunction + defaultReactionEmoji: TransformerFunction + embed: TransformerFunction + emoji: TransformerFunction + entitlement: TransformerFunction + forumTag: TransformerFunction + gatewayBot: TransformerFunction + guild: TransformerFunction + guildOnboarding: TransformerFunction + guildOnboardingPrompt: TransformerFunction + guildOnboardingPromptOption: TransformerFunction< + TProps, + TBehavior, + DiscordGuildOnboardingPromptOption, + GuildOnboardingPromptOption, + {}, + 'unchanged' + > + incidentsData: TransformerFunction + integration: TransformerFunction + interaction: TransformerFunction + interactionCallback: TransformerFunction + interactionCallbackResponse: TransformerFunction< + TProps, + TBehavior, + DiscordInteractionCallbackResponse, + InteractionCallbackResponse, + { shardId?: number } + > + interactionDataOptions: TransformerFunction + interactionDataResolved: TransformerFunction< + TProps, + TBehavior, + DiscordInteractionDataResolved, + InteractionDataResolved, + { shardId?: number; guildId?: BigString }, + 'transform' + > + interactionResource: TransformerFunction + invite: TransformerFunction + inviteStageInstance: TransformerFunction + lobby: TransformerFunction + lobbyMember: TransformerFunction + mediaGalleryItem: TransformerFunction + member: TransformerFunction + message: TransformerFunction + messageCall: TransformerFunction + messageInteractionMetadata: TransformerFunction + messagePin: TransformerFunction + messageSnapshot: TransformerFunction + nameplate: TransformerFunction + poll: TransformerFunction + pollMedia: TransformerFunction + presence: TransformerFunction + role: TransformerFunction + roleColors: TransformerFunction + scheduledEvent: TransformerFunction + scheduledEventRecurrenceRule: TransformerFunction + sku: TransformerFunction + soundboardSound: TransformerFunction snowflake: (snowflake: BigString) => bigint - stageInstance: (bot: Bot, payload: DiscordStageInstance) => SetupDesiredProps - sticker: (bot: Bot, payload: DiscordSticker) => SetupDesiredProps - stickerPack: (bot: Bot, payload: DiscordStickerPack) => StickerPack - subscription: (bot: Bot, payload: DiscordSubscription) => SetupDesiredProps - team: (bot: Bot, payload: DiscordTeam) => Team - template: (bot: Bot, payload: DiscordTemplate) => Template - threadMember: (bot: Bot, payload: DiscordThreadMember, extra?: ThreadMemberTransformerExtra) => ThreadMember - threadMemberGuildCreate: (bot: Bot, payload: DiscordThreadMemberGuildCreate) => ThreadMemberGuildCreate - unfurledMediaItem: (bot: Bot, payload: DiscordUnfurledMediaItem) => UnfurledMediaItem - user: (bot: Bot, payload: DiscordUser) => SetupDesiredProps - userPrimaryGuild: (bot: Bot, payload: DiscordUserPrimaryGuild) => SetupDesiredProps - voiceRegion: (bot: Bot, payload: DiscordVoiceRegion) => VoiceRegion - voiceState: ( - bot: Bot, - payload: DiscordVoiceState, - extra?: { guildId?: BigString }, - ) => SetupDesiredProps - webhook: (bot: Bot, payload: DiscordWebhook) => SetupDesiredProps - welcomeScreen: (bot: Bot, payload: DiscordWelcomeScreen) => WelcomeScreen - widget: (bot: Bot, payload: DiscordGuildWidget) => GuildWidget - widgetSettings: (bot: Bot, payload: DiscordGuildWidgetSettings) => GuildWidgetSettings + stageInstance: TransformerFunction + sticker: TransformerFunction + stickerPack: TransformerFunction + subscription: TransformerFunction + team: TransformerFunction + template: TransformerFunction + threadMember: TransformerFunction + threadMemberGuildCreate: TransformerFunction + unfurledMediaItem: TransformerFunction + user: TransformerFunction + userPrimaryGuild: TransformerFunction + voiceRegion: TransformerFunction + voiceState: TransformerFunction + webhook: TransformerFunction + welcomeScreen: TransformerFunction + widget: TransformerFunction + widgetSettings: TransformerFunction } const defaultCustomizer = (_bot: unknown, _payload: unknown, structure: unknown) => structure @@ -797,3 +774,24 @@ export function createTransformers as unknown as Transformers } + +export type TransformerFunction< + TProps extends TransformersDesiredProperties, + TBehavior extends DesiredPropertiesBehavior, + TPayload, + TTransformed, + TExtra = {}, + // Detecting what kind of transformation is being applied is actually pretty hard, so we just do it manually + TKind extends 'desired-props' | 'transform' | 'unchanged' = 'desired-props', +> = ( + bot: Bot, + payload: TPayload, + extra?: TExtra, +) => TKind extends 'desired-props' + ? TTransformed extends TransformersObjects[keyof TransformersObjects] + ? SetupDesiredProps + : // As fair as i can tell, no transformer is actually in this case + 'ERROR: Invalid transformer kind' + : TKind extends 'transform' + ? TransformProperty + : TTransformed