package transcoder import ( "errors" "fmt" notificationfbs "galaxy/schema/fbs/notification" flatbuffers "github.com/google/flatbuffers/go" ) // GameTurnReadyEvent is the independent Go representation of // `notification.GameTurnReadyEvent`. type GameTurnReadyEvent struct { GameID string TurnNumber int64 } // GameFinishedEvent is the independent Go representation of // `notification.GameFinishedEvent`. type GameFinishedEvent struct { GameID string FinalTurnNumber int64 } // LobbyApplicationSubmittedEvent is the independent Go representation of // `notification.LobbyApplicationSubmittedEvent`. type LobbyApplicationSubmittedEvent struct { GameID string ApplicantUserID string } // LobbyMembershipApprovedEvent is the independent Go representation of // `notification.LobbyMembershipApprovedEvent`. type LobbyMembershipApprovedEvent struct { GameID string } // LobbyMembershipRejectedEvent is the independent Go representation of // `notification.LobbyMembershipRejectedEvent`. type LobbyMembershipRejectedEvent struct { GameID string } // LobbyMembershipBlockedEvent is the independent Go representation of // `notification.LobbyMembershipBlockedEvent`. Reason carries the upstream // lifecycle event that triggered the cascade // (`permanent_blocked`, `deleted`). type LobbyMembershipBlockedEvent struct { GameID string MembershipUserID string Reason string } // LobbyInviteCreatedEvent is the independent Go representation of // `notification.LobbyInviteCreatedEvent`. type LobbyInviteCreatedEvent struct { GameID string InviterUserID string } // LobbyInviteRedeemedEvent is the independent Go representation of // `notification.LobbyInviteRedeemedEvent`. type LobbyInviteRedeemedEvent struct { GameID string InviteeUserID string } // LobbyRaceNameRegistrationEligibleEvent is the independent Go // representation of `notification.LobbyRaceNameRegistrationEligibleEvent`. type LobbyRaceNameRegistrationEligibleEvent struct { GameID string RaceName string EligibleUntilMs int64 } // LobbyRaceNameRegisteredEvent is the independent Go representation of // `notification.LobbyRaceNameRegisteredEvent`. type LobbyRaceNameRegisteredEvent struct { RaceName string } // GameTurnReadyEventToPayload converts GameTurnReadyEvent to FlatBuffers bytes // suitable for the authenticated gateway push transport. func GameTurnReadyEventToPayload(event *GameTurnReadyEvent) ([]byte, error) { if event == nil { return nil, errors.New("encode game turn ready payload: event is nil") } if event.GameID == "" { return nil, errors.New("encode game turn ready payload: game_id is empty") } builder := flatbuffers.NewBuilder(64) gameID := builder.CreateString(event.GameID) notificationfbs.GameTurnReadyEventStart(builder) notificationfbs.GameTurnReadyEventAddGameId(builder, gameID) notificationfbs.GameTurnReadyEventAddTurnNumber(builder, event.TurnNumber) offset := notificationfbs.GameTurnReadyEventEnd(builder) notificationfbs.FinishGameTurnReadyEventBuffer(builder, offset) return builder.FinishedBytes(), nil } // PayloadToGameTurnReadyEvent converts FlatBuffers payload bytes into // GameTurnReadyEvent. func PayloadToGameTurnReadyEvent(data []byte) (result *GameTurnReadyEvent, err error) { if len(data) == 0 { return nil, errors.New("decode game turn ready payload: data is empty") } defer recoverNotificationDecodePanic("decode game turn ready payload", &result, &err) event := notificationfbs.GetRootAsGameTurnReadyEvent(data, 0) gameID, err := requiredNotificationString(event.GameId(), "game_id") if err != nil { return nil, fmt.Errorf("decode game turn ready payload: %w", err) } return &GameTurnReadyEvent{ GameID: gameID, TurnNumber: event.TurnNumber(), }, nil } // GameFinishedEventToPayload converts GameFinishedEvent to FlatBuffers bytes // suitable for the authenticated gateway push transport. func GameFinishedEventToPayload(event *GameFinishedEvent) ([]byte, error) { if event == nil { return nil, errors.New("encode game finished payload: event is nil") } if event.GameID == "" { return nil, errors.New("encode game finished payload: game_id is empty") } builder := flatbuffers.NewBuilder(64) gameID := builder.CreateString(event.GameID) notificationfbs.GameFinishedEventStart(builder) notificationfbs.GameFinishedEventAddGameId(builder, gameID) notificationfbs.GameFinishedEventAddFinalTurnNumber(builder, event.FinalTurnNumber) offset := notificationfbs.GameFinishedEventEnd(builder) notificationfbs.FinishGameFinishedEventBuffer(builder, offset) return builder.FinishedBytes(), nil } // PayloadToGameFinishedEvent converts FlatBuffers payload bytes into // GameFinishedEvent. func PayloadToGameFinishedEvent(data []byte) (result *GameFinishedEvent, err error) { if len(data) == 0 { return nil, errors.New("decode game finished payload: data is empty") } defer recoverNotificationDecodePanic("decode game finished payload", &result, &err) event := notificationfbs.GetRootAsGameFinishedEvent(data, 0) gameID, err := requiredNotificationString(event.GameId(), "game_id") if err != nil { return nil, fmt.Errorf("decode game finished payload: %w", err) } return &GameFinishedEvent{ GameID: gameID, FinalTurnNumber: event.FinalTurnNumber(), }, nil } // LobbyApplicationSubmittedEventToPayload converts // LobbyApplicationSubmittedEvent to FlatBuffers bytes suitable for the // authenticated gateway push transport. func LobbyApplicationSubmittedEventToPayload(event *LobbyApplicationSubmittedEvent) ([]byte, error) { if event == nil { return nil, errors.New("encode lobby application submitted payload: event is nil") } if event.GameID == "" { return nil, errors.New("encode lobby application submitted payload: game_id is empty") } if event.ApplicantUserID == "" { return nil, errors.New("encode lobby application submitted payload: applicant_user_id is empty") } builder := flatbuffers.NewBuilder(96) gameID := builder.CreateString(event.GameID) applicantUserID := builder.CreateString(event.ApplicantUserID) notificationfbs.LobbyApplicationSubmittedEventStart(builder) notificationfbs.LobbyApplicationSubmittedEventAddGameId(builder, gameID) notificationfbs.LobbyApplicationSubmittedEventAddApplicantUserId(builder, applicantUserID) offset := notificationfbs.LobbyApplicationSubmittedEventEnd(builder) notificationfbs.FinishLobbyApplicationSubmittedEventBuffer(builder, offset) return builder.FinishedBytes(), nil } // PayloadToLobbyApplicationSubmittedEvent converts FlatBuffers payload bytes // into LobbyApplicationSubmittedEvent. func PayloadToLobbyApplicationSubmittedEvent(data []byte) (result *LobbyApplicationSubmittedEvent, err error) { if len(data) == 0 { return nil, errors.New("decode lobby application submitted payload: data is empty") } defer recoverNotificationDecodePanic("decode lobby application submitted payload", &result, &err) event := notificationfbs.GetRootAsLobbyApplicationSubmittedEvent(data, 0) gameID, err := requiredNotificationString(event.GameId(), "game_id") if err != nil { return nil, fmt.Errorf("decode lobby application submitted payload: %w", err) } applicantUserID, err := requiredNotificationString(event.ApplicantUserId(), "applicant_user_id") if err != nil { return nil, fmt.Errorf("decode lobby application submitted payload: %w", err) } return &LobbyApplicationSubmittedEvent{ GameID: gameID, ApplicantUserID: applicantUserID, }, nil } // LobbyMembershipApprovedEventToPayload converts LobbyMembershipApprovedEvent // to FlatBuffers bytes suitable for the authenticated gateway push transport. func LobbyMembershipApprovedEventToPayload(event *LobbyMembershipApprovedEvent) ([]byte, error) { if event == nil { return nil, errors.New("encode lobby membership approved payload: event is nil") } if event.GameID == "" { return nil, errors.New("encode lobby membership approved payload: game_id is empty") } builder := flatbuffers.NewBuilder(48) gameID := builder.CreateString(event.GameID) notificationfbs.LobbyMembershipApprovedEventStart(builder) notificationfbs.LobbyMembershipApprovedEventAddGameId(builder, gameID) offset := notificationfbs.LobbyMembershipApprovedEventEnd(builder) notificationfbs.FinishLobbyMembershipApprovedEventBuffer(builder, offset) return builder.FinishedBytes(), nil } // PayloadToLobbyMembershipApprovedEvent converts FlatBuffers payload bytes // into LobbyMembershipApprovedEvent. func PayloadToLobbyMembershipApprovedEvent(data []byte) (result *LobbyMembershipApprovedEvent, err error) { if len(data) == 0 { return nil, errors.New("decode lobby membership approved payload: data is empty") } defer recoverNotificationDecodePanic("decode lobby membership approved payload", &result, &err) event := notificationfbs.GetRootAsLobbyMembershipApprovedEvent(data, 0) gameID, err := requiredNotificationString(event.GameId(), "game_id") if err != nil { return nil, fmt.Errorf("decode lobby membership approved payload: %w", err) } return &LobbyMembershipApprovedEvent{GameID: gameID}, nil } // LobbyMembershipRejectedEventToPayload converts LobbyMembershipRejectedEvent // to FlatBuffers bytes suitable for the authenticated gateway push transport. func LobbyMembershipRejectedEventToPayload(event *LobbyMembershipRejectedEvent) ([]byte, error) { if event == nil { return nil, errors.New("encode lobby membership rejected payload: event is nil") } if event.GameID == "" { return nil, errors.New("encode lobby membership rejected payload: game_id is empty") } builder := flatbuffers.NewBuilder(48) gameID := builder.CreateString(event.GameID) notificationfbs.LobbyMembershipRejectedEventStart(builder) notificationfbs.LobbyMembershipRejectedEventAddGameId(builder, gameID) offset := notificationfbs.LobbyMembershipRejectedEventEnd(builder) notificationfbs.FinishLobbyMembershipRejectedEventBuffer(builder, offset) return builder.FinishedBytes(), nil } // PayloadToLobbyMembershipRejectedEvent converts FlatBuffers payload bytes // into LobbyMembershipRejectedEvent. func PayloadToLobbyMembershipRejectedEvent(data []byte) (result *LobbyMembershipRejectedEvent, err error) { if len(data) == 0 { return nil, errors.New("decode lobby membership rejected payload: data is empty") } defer recoverNotificationDecodePanic("decode lobby membership rejected payload", &result, &err) event := notificationfbs.GetRootAsLobbyMembershipRejectedEvent(data, 0) gameID, err := requiredNotificationString(event.GameId(), "game_id") if err != nil { return nil, fmt.Errorf("decode lobby membership rejected payload: %w", err) } return &LobbyMembershipRejectedEvent{GameID: gameID}, nil } // LobbyMembershipBlockedEventToPayload converts LobbyMembershipBlockedEvent // to FlatBuffers bytes suitable for the authenticated gateway push // transport. func LobbyMembershipBlockedEventToPayload(event *LobbyMembershipBlockedEvent) ([]byte, error) { if event == nil { return nil, errors.New("encode lobby membership blocked payload: event is nil") } if event.GameID == "" { return nil, errors.New("encode lobby membership blocked payload: game_id is empty") } if event.MembershipUserID == "" { return nil, errors.New("encode lobby membership blocked payload: membership_user_id is empty") } if event.Reason == "" { return nil, errors.New("encode lobby membership blocked payload: reason is empty") } builder := flatbuffers.NewBuilder(96) gameID := builder.CreateString(event.GameID) membershipUserID := builder.CreateString(event.MembershipUserID) reason := builder.CreateString(event.Reason) notificationfbs.LobbyMembershipBlockedEventStart(builder) notificationfbs.LobbyMembershipBlockedEventAddGameId(builder, gameID) notificationfbs.LobbyMembershipBlockedEventAddMembershipUserId(builder, membershipUserID) notificationfbs.LobbyMembershipBlockedEventAddReason(builder, reason) offset := notificationfbs.LobbyMembershipBlockedEventEnd(builder) notificationfbs.FinishLobbyMembershipBlockedEventBuffer(builder, offset) return builder.FinishedBytes(), nil } // PayloadToLobbyMembershipBlockedEvent converts FlatBuffers payload bytes // into LobbyMembershipBlockedEvent. func PayloadToLobbyMembershipBlockedEvent(data []byte) (result *LobbyMembershipBlockedEvent, err error) { if len(data) == 0 { return nil, errors.New("decode lobby membership blocked payload: data is empty") } defer recoverNotificationDecodePanic("decode lobby membership blocked payload", &result, &err) event := notificationfbs.GetRootAsLobbyMembershipBlockedEvent(data, 0) gameID, err := requiredNotificationString(event.GameId(), "game_id") if err != nil { return nil, fmt.Errorf("decode lobby membership blocked payload: %w", err) } membershipUserID, err := requiredNotificationString(event.MembershipUserId(), "membership_user_id") if err != nil { return nil, fmt.Errorf("decode lobby membership blocked payload: %w", err) } reason, err := requiredNotificationString(event.Reason(), "reason") if err != nil { return nil, fmt.Errorf("decode lobby membership blocked payload: %w", err) } return &LobbyMembershipBlockedEvent{ GameID: gameID, MembershipUserID: membershipUserID, Reason: reason, }, nil } // LobbyInviteCreatedEventToPayload converts LobbyInviteCreatedEvent to // FlatBuffers bytes suitable for the authenticated gateway push transport. func LobbyInviteCreatedEventToPayload(event *LobbyInviteCreatedEvent) ([]byte, error) { if event == nil { return nil, errors.New("encode lobby invite created payload: event is nil") } if event.GameID == "" { return nil, errors.New("encode lobby invite created payload: game_id is empty") } if event.InviterUserID == "" { return nil, errors.New("encode lobby invite created payload: inviter_user_id is empty") } builder := flatbuffers.NewBuilder(96) gameID := builder.CreateString(event.GameID) inviterUserID := builder.CreateString(event.InviterUserID) notificationfbs.LobbyInviteCreatedEventStart(builder) notificationfbs.LobbyInviteCreatedEventAddGameId(builder, gameID) notificationfbs.LobbyInviteCreatedEventAddInviterUserId(builder, inviterUserID) offset := notificationfbs.LobbyInviteCreatedEventEnd(builder) notificationfbs.FinishLobbyInviteCreatedEventBuffer(builder, offset) return builder.FinishedBytes(), nil } // PayloadToLobbyInviteCreatedEvent converts FlatBuffers payload bytes into // LobbyInviteCreatedEvent. func PayloadToLobbyInviteCreatedEvent(data []byte) (result *LobbyInviteCreatedEvent, err error) { if len(data) == 0 { return nil, errors.New("decode lobby invite created payload: data is empty") } defer recoverNotificationDecodePanic("decode lobby invite created payload", &result, &err) event := notificationfbs.GetRootAsLobbyInviteCreatedEvent(data, 0) gameID, err := requiredNotificationString(event.GameId(), "game_id") if err != nil { return nil, fmt.Errorf("decode lobby invite created payload: %w", err) } inviterUserID, err := requiredNotificationString(event.InviterUserId(), "inviter_user_id") if err != nil { return nil, fmt.Errorf("decode lobby invite created payload: %w", err) } return &LobbyInviteCreatedEvent{ GameID: gameID, InviterUserID: inviterUserID, }, nil } // LobbyInviteRedeemedEventToPayload converts LobbyInviteRedeemedEvent to // FlatBuffers bytes suitable for the authenticated gateway push transport. func LobbyInviteRedeemedEventToPayload(event *LobbyInviteRedeemedEvent) ([]byte, error) { if event == nil { return nil, errors.New("encode lobby invite redeemed payload: event is nil") } if event.GameID == "" { return nil, errors.New("encode lobby invite redeemed payload: game_id is empty") } if event.InviteeUserID == "" { return nil, errors.New("encode lobby invite redeemed payload: invitee_user_id is empty") } builder := flatbuffers.NewBuilder(96) gameID := builder.CreateString(event.GameID) inviteeUserID := builder.CreateString(event.InviteeUserID) notificationfbs.LobbyInviteRedeemedEventStart(builder) notificationfbs.LobbyInviteRedeemedEventAddGameId(builder, gameID) notificationfbs.LobbyInviteRedeemedEventAddInviteeUserId(builder, inviteeUserID) offset := notificationfbs.LobbyInviteRedeemedEventEnd(builder) notificationfbs.FinishLobbyInviteRedeemedEventBuffer(builder, offset) return builder.FinishedBytes(), nil } // PayloadToLobbyInviteRedeemedEvent converts FlatBuffers payload bytes into // LobbyInviteRedeemedEvent. func PayloadToLobbyInviteRedeemedEvent(data []byte) (result *LobbyInviteRedeemedEvent, err error) { if len(data) == 0 { return nil, errors.New("decode lobby invite redeemed payload: data is empty") } defer recoverNotificationDecodePanic("decode lobby invite redeemed payload", &result, &err) event := notificationfbs.GetRootAsLobbyInviteRedeemedEvent(data, 0) gameID, err := requiredNotificationString(event.GameId(), "game_id") if err != nil { return nil, fmt.Errorf("decode lobby invite redeemed payload: %w", err) } inviteeUserID, err := requiredNotificationString(event.InviteeUserId(), "invitee_user_id") if err != nil { return nil, fmt.Errorf("decode lobby invite redeemed payload: %w", err) } return &LobbyInviteRedeemedEvent{ GameID: gameID, InviteeUserID: inviteeUserID, }, nil } // LobbyRaceNameRegistrationEligibleEventToPayload converts // LobbyRaceNameRegistrationEligibleEvent to FlatBuffers bytes suitable for // the authenticated gateway push transport. func LobbyRaceNameRegistrationEligibleEventToPayload(event *LobbyRaceNameRegistrationEligibleEvent) ([]byte, error) { if event == nil { return nil, errors.New("encode lobby race name registration eligible payload: event is nil") } if event.GameID == "" { return nil, errors.New("encode lobby race name registration eligible payload: game_id is empty") } if event.RaceName == "" { return nil, errors.New("encode lobby race name registration eligible payload: race_name is empty") } builder := flatbuffers.NewBuilder(96) gameID := builder.CreateString(event.GameID) raceName := builder.CreateString(event.RaceName) notificationfbs.LobbyRaceNameRegistrationEligibleEventStart(builder) notificationfbs.LobbyRaceNameRegistrationEligibleEventAddGameId(builder, gameID) notificationfbs.LobbyRaceNameRegistrationEligibleEventAddRaceName(builder, raceName) notificationfbs.LobbyRaceNameRegistrationEligibleEventAddEligibleUntilMs(builder, event.EligibleUntilMs) offset := notificationfbs.LobbyRaceNameRegistrationEligibleEventEnd(builder) notificationfbs.FinishLobbyRaceNameRegistrationEligibleEventBuffer(builder, offset) return builder.FinishedBytes(), nil } // PayloadToLobbyRaceNameRegistrationEligibleEvent converts FlatBuffers // payload bytes into LobbyRaceNameRegistrationEligibleEvent. func PayloadToLobbyRaceNameRegistrationEligibleEvent(data []byte) (result *LobbyRaceNameRegistrationEligibleEvent, err error) { if len(data) == 0 { return nil, errors.New("decode lobby race name registration eligible payload: data is empty") } defer recoverNotificationDecodePanic("decode lobby race name registration eligible payload", &result, &err) event := notificationfbs.GetRootAsLobbyRaceNameRegistrationEligibleEvent(data, 0) gameID, err := requiredNotificationString(event.GameId(), "game_id") if err != nil { return nil, fmt.Errorf("decode lobby race name registration eligible payload: %w", err) } raceName, err := requiredNotificationString(event.RaceName(), "race_name") if err != nil { return nil, fmt.Errorf("decode lobby race name registration eligible payload: %w", err) } return &LobbyRaceNameRegistrationEligibleEvent{ GameID: gameID, RaceName: raceName, EligibleUntilMs: event.EligibleUntilMs(), }, nil } // LobbyRaceNameRegisteredEventToPayload converts LobbyRaceNameRegisteredEvent // to FlatBuffers bytes suitable for the authenticated gateway push transport. func LobbyRaceNameRegisteredEventToPayload(event *LobbyRaceNameRegisteredEvent) ([]byte, error) { if event == nil { return nil, errors.New("encode lobby race name registered payload: event is nil") } if event.RaceName == "" { return nil, errors.New("encode lobby race name registered payload: race_name is empty") } builder := flatbuffers.NewBuilder(48) raceName := builder.CreateString(event.RaceName) notificationfbs.LobbyRaceNameRegisteredEventStart(builder) notificationfbs.LobbyRaceNameRegisteredEventAddRaceName(builder, raceName) offset := notificationfbs.LobbyRaceNameRegisteredEventEnd(builder) notificationfbs.FinishLobbyRaceNameRegisteredEventBuffer(builder, offset) return builder.FinishedBytes(), nil } // PayloadToLobbyRaceNameRegisteredEvent converts FlatBuffers payload bytes // into LobbyRaceNameRegisteredEvent. func PayloadToLobbyRaceNameRegisteredEvent(data []byte) (result *LobbyRaceNameRegisteredEvent, err error) { if len(data) == 0 { return nil, errors.New("decode lobby race name registered payload: data is empty") } defer recoverNotificationDecodePanic("decode lobby race name registered payload", &result, &err) event := notificationfbs.GetRootAsLobbyRaceNameRegisteredEvent(data, 0) raceName, err := requiredNotificationString(event.RaceName(), "race_name") if err != nil { return nil, fmt.Errorf("decode lobby race name registered payload: %w", err) } return &LobbyRaceNameRegisteredEvent{RaceName: raceName}, nil } func requiredNotificationString(value []byte, field string) (string, error) { if len(value) == 0 { return "", fmt.Errorf("%s is missing", field) } return string(value), nil } func recoverNotificationDecodePanic[T any](message string, result **T, err *error) { if recovered := recover(); recovered != nil { *result = nil *err = fmt.Errorf("%s: panic recovered: %v", message, recovered) } }