parse method

GatewayEvent parse(
  1. String eventType,
  2. Map<String, dynamic> data
)

Parses a dispatch eventType with its associated data payload.

Returns an UnknownGatewayEvent if the event type is unrecognized or if deserialization fails.

Implementation

GatewayEvent parse(String eventType, Map<String, dynamic> data) {
  try {
    return switch (eventType) {
      'READY' => _parseReady(data),
      'RESUMED' => const ResumedEvent(),
      'MESSAGE_CREATE' => MessageCreateEvent(
        message: MessageResponseSchema.fromJson(data),
      ),
      'MESSAGE_UPDATE' => MessageUpdateEvent(
        message: MessageResponseSchema.fromJson(data),
      ),
      'MESSAGE_DELETE' => MessageDeleteEvent(
        channelId: data['channel_id'] as String,
        messageId: data['id'] as String,
        guildId: data['guild_id'] as String?,
      ),
      'MESSAGE_REACTION_ADD' => MessageReactionAddEvent(
        channelId: data['channel_id'] as String,
        messageId: data['message_id'] as String,
        userId: data['user_id'] as String,
        emoji: ReactionEmoji.fromJson(data['emoji'] as Map<String, dynamic>),
        guildId: data['guild_id'] as String?,
      ),
      'MESSAGE_REACTION_REMOVE' => MessageReactionRemoveEvent(
        channelId: data['channel_id'] as String,
        messageId: data['message_id'] as String,
        userId: data['user_id'] as String,
        emoji: ReactionEmoji.fromJson(data['emoji'] as Map<String, dynamic>),
        guildId: data['guild_id'] as String?,
      ),
      'MESSAGE_REACTION_REMOVE_ALL' => MessageReactionRemoveAllEvent(
        channelId: data['channel_id'] as String,
        messageId: data['message_id'] as String,
        guildId: data['guild_id'] as String?,
      ),
      'MESSAGE_REACTION_REMOVE_EMOJI' => MessageReactionRemoveEmojiEvent(
        channelId: data['channel_id'] as String,
        messageId: data['message_id'] as String,
        emoji: ReactionEmoji.fromJson(data['emoji'] as Map<String, dynamic>),
        guildId: data['guild_id'] as String?,
      ),
      'CHANNEL_CREATE' => ChannelCreateEvent(
        channel: ChannelResponse.fromJson(data),
      ),
      'CHANNEL_UPDATE' => ChannelUpdateEvent(
        channel: ChannelResponse.fromJson(data),
      ),
      'CHANNEL_DELETE' => ChannelDeleteEvent(
        channel: ChannelResponse.fromJson(data),
      ),
      'GUILD_CREATE' => GuildCreateEvent(
        guild: GuildCreateData.fromJson(data),
      ),
      'GUILD_UPDATE' => GuildUpdateEvent(
        guild: GuildCreateData.fromJson(data),
      ),
      'GUILD_DELETE' => GuildDeleteEvent(
        guildId: data['id'] as String,
        unavailable: data['unavailable'] as bool? ?? false,
      ),
      'GUILD_MEMBER_ADD' => GuildMemberAddEvent(
        guildId: data['guild_id'] as String,
        member: GuildMemberResponse.fromJson(data),
      ),
      'GUILD_MEMBER_UPDATE' => GuildMemberUpdateEvent(
        guildId: data['guild_id'] as String,
        member: GuildMemberResponse.fromJson(data),
      ),
      'GUILD_MEMBER_REMOVE' => GuildMemberRemoveEvent(
        guildId: data['guild_id'] as String,
        userId:
            data['user_id'] as String? ??
            (data['user'] as Map<String, dynamic>)['id'] as String,
      ),
      'PRESENCE_UPDATE' => _parsePresenceUpdate(data),
      'TYPING_START' => TypingStartEvent(
        channelId: data['channel_id'] as String,
        userId: data['user_id'] as String,
        timestamp: DateTime.fromMillisecondsSinceEpoch(
          (data['timestamp'] as num).toInt() * 1000,
        ),
        guildId: data['guild_id'] as String?,
        member: GuildMemberResponse.fromJson(
          data['member'] as Map<String, dynamic>,
        ),
      ),
      'RELATIONSHIP_ADD' => RelationshipAddEvent(
        relationship: RelationshipResponse.fromJson(data),
      ),
      'RELATIONSHIP_UPDATE' => RelationshipUpdateEvent(
        relationship: RelationshipResponse.fromJson(data),
      ),
      'RELATIONSHIP_REMOVE' => RelationshipRemoveEvent(
        userId: data['id'] as String,
        type: RelationshipTypes.fromJson(data['type'] as int),
      ),

      // User
      'USER_UPDATE' => UserUpdateEvent(
        user: UserPrivateResponse.fromJson(data),
      ),
      'USER_SETTINGS_UPDATE' => UserSettingsUpdateEvent(
        settings: UserSettingsResponse.fromJson(data),
      ),
      'USER_GUILD_SETTINGS_UPDATE' => UserGuildSettingsUpdateEvent(
        guildId: data['guild_id'] as String,
        data: data,
      ),
      // Note: USER_PINNED_DMS_UPDATE sends `d` as a plain array of strings,
      // but gateway_connection.dart casts `d` as Map<String, dynamic>.
      // This means the event will throw and fall through to UnknownGatewayEvent
      // until special handling is added at the _onMessage level.
      'USER_PINNED_DMS_UPDATE' => UserPinnedDmsUpdateEvent(
        pinnedDmChannelIds: (data as List<dynamic>?)?.cast<String>() ?? [],
      ),
      'USER_NOTE_UPDATE' => UserNoteUpdateEvent(
        userId: data['id'] as String,
        note: data['note'] as String?,
      ),
      'USER_CONNECTIONS_UPDATE' => UserConnectionsUpdateEvent(data: data),
      'AUTH_SESSION_CHANGE' => AuthSessionChangeEvent(
        newToken: data['new_token'] as String?,
        newAuthSessionIdHash: data['new_auth_session_id_hash'] as String?,
      ),

      // Messages
      'MESSAGE_DELETE_BULK' => MessageDeleteBulkEvent(
        channelId: data['channel_id'] as String,
        ids: (data['ids'] as List<dynamic>).cast<String>(),
        guildId: data['guild_id'] as String?,
      ),
      'MESSAGE_ACK' => MessageAckEvent(
        channelId: data['channel_id'] as String,
        messageId: data['message_id'] as String,
        mentionCount: data['mention_count'] as int?,
        manual: data['manual'] as bool?,
      ),
      'MESSAGE_REACTION_ADD_MANY' => MessageReactionAddManyEvent(
        channelId: data['channel_id'] as String,
        messageId: data['message_id'] as String,
        reactions: (data['reactions'] as List<dynamic>)
            .cast<Map<String, dynamic>>(),
        guildId: data['guild_id'] as String?,
      ),

      // Channels
      'CHANNEL_UPDATE_BULK' => ChannelUpdateBulkEvent(
        channels: (data['channels'] as List<dynamic>)
            .map((e) => ChannelResponse.fromJson(e as Map<String, Object?>))
            .toList(),
      ),
      'CHANNEL_PINS_UPDATE' => ChannelPinsUpdateEvent(
        channelId: data['channel_id'] as String,
        guildId: data['guild_id'] as String?,
        lastPinTimestamp: data['last_pin_timestamp'] as String?,
      ),
      'CHANNEL_PINS_ACK' => ChannelPinsAckEvent(
        channelId: data['channel_id'] as String,
        lastPinTimestamp: data['last_pin_timestamp'] as String?,
      ),
      'CHANNEL_RECIPIENT_ADD' => ChannelRecipientAddEvent(
        channelId: data['channel_id'] as String,
        user: UserPartialResponse.fromJson(
          data['user'] as Map<String, Object?>,
        ),
      ),
      'CHANNEL_RECIPIENT_REMOVE' => ChannelRecipientRemoveEvent(
        channelId: data['channel_id'] as String,
        user: UserPartialResponse.fromJson(
          data['user'] as Map<String, Object?>,
        ),
      ),
      'PASSIVE_UPDATES' => _parsePassiveUpdates(data),

      // Guild roles
      'GUILD_ROLE_CREATE' => GuildRoleCreateEvent(
        guildId: data['guild_id'] as String,
        role: GuildRoleResponse.fromJson(
          data['role'] as Map<String, Object?>,
        ),
      ),
      'GUILD_ROLE_UPDATE' => GuildRoleUpdateEvent(
        guildId: data['guild_id'] as String,
        role: GuildRoleResponse.fromJson(
          data['role'] as Map<String, Object?>,
        ),
      ),
      'GUILD_ROLE_DELETE' => GuildRoleDeleteEvent(
        guildId: data['guild_id'] as String,
        roleId: data['role_id'] as String,
      ),
      'GUILD_ROLE_UPDATE_BULK' => GuildRoleUpdateBulkEvent(
        guildId: data['guild_id'] as String,
        roles: (data['roles'] as List<dynamic>)
            .map((e) => GuildRoleResponse.fromJson(e as Map<String, Object?>))
            .toList(),
      ),

      // Guild bans
      'GUILD_BAN_ADD' => GuildBanAddEvent(
        guildId: data['guild_id'] as String,
        user: UserPartialResponse.fromJson(
          data['user'] as Map<String, Object?>,
        ),
      ),
      'GUILD_BAN_REMOVE' => GuildBanRemoveEvent(
        guildId: data['guild_id'] as String,
        user: UserPartialResponse.fromJson(
          data['user'] as Map<String, Object?>,
        ),
      ),

      // Guild emojis & stickers
      'GUILD_EMOJIS_UPDATE' => GuildEmojisUpdateEvent(
        guildId: data['guild_id'] as String,
        emojis: (data['emojis'] as List<dynamic>)
            .map(
              (e) => GuildEmojiResponse.fromJson(e as Map<String, Object?>),
            )
            .toList(),
      ),
      'GUILD_STICKERS_UPDATE' => GuildStickersUpdateEvent(
        guildId: data['guild_id'] as String,
        stickers: (data['stickers'] as List<dynamic>)
            .map(
              (e) => GuildStickerResponse.fromJson(e as Map<String, Object?>),
            )
            .toList(),
      ),

      // Guild sync & members
      'GUILD_SYNC' => GuildSyncEvent(guild: GuildCreateData.fromJson(data)),
      'GUILD_MEMBERS_CHUNK' => GuildMembersChunkEvent(
        guildId: data['guild_id'] as String,
        members: (data['members'] as List<dynamic>)
            .map(
              (e) => GuildMemberResponse.fromJson(e as Map<String, dynamic>),
            )
            .toList(),
        chunkIndex: data['chunk_index'] as int,
        chunkCount: data['chunk_count'] as int,
        notFound: (data['not_found'] as List<dynamic>?)?.cast<String>(),
        presences: (data['presences'] as List<dynamic>?)
            ?.cast<Map<String, dynamic>>(),
        nonce: data['nonce'] as String?,
      ),
      'GUILD_MEMBER_LIST_UPDATE' => _parseMemberListUpdate(data),

      // Presence
      'PRESENCE_UPDATE_BULK' => PresenceUpdateBulkEvent(
        presences: (data['presences'] as List<dynamic>)
            .cast<Map<String, dynamic>>(),
        guildId: data['guild_id'] as String?,
      ),

      // Voice
      'VOICE_STATE_UPDATE' => VoiceStateUpdateEvent(
        state: VoiceState.fromJson(data),
      ),
      'VOICE_SERVER_UPDATE' => VoiceServerUpdateEvent(
        token: data['token'] as String,
        endpoint: data['endpoint'] as String,
        connectionId: data['connection_id'] as String,
        guildId: data['guild_id'] as String?,
        channelId: data['channel_id'] as String?,
        e2eeKey: data['e2ee_key'] as String?,
      ),

      // Calls
      'CALL_CREATE' => _parseCallCreate(data),
      'CALL_UPDATE' => _parseCallUpdate(data),
      'CALL_DELETE' => CallDeleteEvent(
        channelId: data['channel_id'] as String,
      ),

      // Invites
      'INVITE_CREATE' => InviteCreateEvent(data: data),
      'INVITE_DELETE' => InviteDeleteEvent(
        code: data['code'] as String,
        guildId: data['guild_id'] as String,
      ),

      // Saved messages & mentions
      'SAVED_MESSAGE_CREATE' => SavedMessageCreateEvent(
        message: MessageResponseSchema.fromJson(data),
      ),
      'SAVED_MESSAGE_DELETE' => SavedMessageDeleteEvent(
        messageId: data['message_id'] as String,
      ),
      'RECENT_MENTION_DELETE' => RecentMentionDeleteEvent(
        messageId: data['message_id'] as String,
      ),

      // Misc
      'WEBHOOKS_UPDATE' => WebhooksUpdateEvent(
        channelId: data['channel_id'] as String,
        guildId: data['guild_id'] as String,
      ),
      'FAVORITE_MEME_CREATE' => FavoriteMemeCreateEvent(data: data),
      'FAVORITE_MEME_UPDATE' => FavoriteMemeUpdateEvent(data: data),
      'FAVORITE_MEME_DELETE' => FavoriteMemeDeleteEvent(
        id: data['id'] as String,
      ),
      'SESSIONS_REPLACE' => const SessionsReplaceEvent(),

      _ => UnknownGatewayEvent(eventType: eventType, data: data),
    };
  } catch (_) {
    return UnknownGatewayEvent(eventType: eventType, data: data);
  }
}