package sub2api import ( "bytes" "encoding/json" "fmt" "strconv" "strings" ) func decodeFlexibleID(raw json.RawMessage) (string, error) { if len(raw) == 0 || bytes.Equal(raw, []byte("null")) { return "", nil } var asString string if err := json.Unmarshal(raw, &asString); err == nil { return asString, nil } decoder := json.NewDecoder(bytes.NewReader(raw)) decoder.UseNumber() var asNumber json.Number if err := decoder.Decode(&asNumber); err == nil { return asNumber.String(), nil } return "", fmt.Errorf("unsupported id payload: %s", string(raw)) } func flexibleIDValue(raw string) any { trimmed := strings.TrimSpace(raw) if trimmed == "" { return "" } if id, err := strconv.ParseInt(trimmed, 10, 64); err == nil { return id } return trimmed } func flexibleIDSliceValues(raw []string) []any { values := make([]any, 0, len(raw)) for _, item := range raw { values = append(values, flexibleIDValue(item)) } return values } func (r CreateChannelRequest) MarshalJSON() ([]byte, error) { modelMapping := map[string]map[string]string{} platform := strings.TrimSpace(r.Platform) if platform == "" { platform = "openai" } if len(r.ModelMapping) > 0 { inner := make(map[string]string, len(r.ModelMapping)) for key, value := range r.ModelMapping { inner[key] = value } modelMapping[platform] = inner } modelPricing := make([]ChannelModelPricing, 0, len(r.ModelPricing)) for _, entry := range r.ModelPricing { pricing := entry if strings.TrimSpace(pricing.Platform) == "" { pricing.Platform = platform } modelPricing = append(modelPricing, pricing) } return json.Marshal(struct { Name string `json:"name"` GroupIDs []any `json:"group_ids"` ModelMapping map[string]map[string]string `json:"model_mapping,omitempty"` ModelPricing []ChannelModelPricing `json:"model_pricing,omitempty"` RestrictModels bool `json:"restrict_models,omitempty"` BillingModelSource string `json:"billing_model_source,omitempty"` }{ Name: r.Name, GroupIDs: flexibleIDSliceValues(r.GroupIDs), ModelMapping: modelMapping, ModelPricing: modelPricing, RestrictModels: r.RestrictModels, BillingModelSource: r.BillingModelSource, }) } func (r CreatePlanRequest) MarshalJSON() ([]byte, error) { return json.Marshal(struct { GroupID any `json:"group_id"` Name string `json:"name"` Price float64 `json:"price"` ValidityDays int `json:"validity_days"` ValidityUnit string `json:"validity_unit"` }{ GroupID: flexibleIDValue(r.GroupID), Name: r.Name, Price: r.Price, ValidityDays: r.ValidityDays, ValidityUnit: r.ValidityUnit, }) } func (r CreateAccountRequest) MarshalJSON() ([]byte, error) { return json.Marshal(struct { Name string `json:"name"` Platform string `json:"platform"` Type string `json:"type"` Credentials map[string]any `json:"credentials"` GroupIDs []any `json:"group_ids"` }{ Name: r.Name, Platform: r.Platform, Type: r.Type, Credentials: r.Credentials, GroupIDs: flexibleIDSliceValues(r.GroupIDs), }) } func (r AssignSubscriptionRequest) MarshalJSON() ([]byte, error) { return json.Marshal(struct { UserID any `json:"user_id"` GroupID any `json:"group_id"` DurationDays int `json:"validity_days,omitempty"` }{ UserID: flexibleIDValue(r.UserID), GroupID: flexibleIDValue(r.GroupID), DurationDays: r.DurationDays, }) } func (r *NamedResource) UnmarshalJSON(data []byte) error { var aux struct { ID json.RawMessage `json:"id"` Name string `json:"name"` } if err := json.Unmarshal(data, &aux); err != nil { return err } id, err := decodeFlexibleID(aux.ID) if err != nil { return err } r.ID = id r.Name = aux.Name return nil } func (r *GroupRef) UnmarshalJSON(data []byte) error { var aux struct { ID json.RawMessage `json:"id"` Name string `json:"name"` } if err := json.Unmarshal(data, &aux); err != nil { return err } id, err := decodeFlexibleID(aux.ID) if err != nil { return err } r.ID = id r.Name = aux.Name return nil } func (r *ChannelRef) UnmarshalJSON(data []byte) error { var aux struct { ID json.RawMessage `json:"id"` Name string `json:"name"` } if err := json.Unmarshal(data, &aux); err != nil { return err } id, err := decodeFlexibleID(aux.ID) if err != nil { return err } r.ID = id r.Name = aux.Name return nil } func (r *PlanRef) UnmarshalJSON(data []byte) error { var aux struct { ID json.RawMessage `json:"id"` Name string `json:"name"` } if err := json.Unmarshal(data, &aux); err != nil { return err } id, err := decodeFlexibleID(aux.ID) if err != nil { return err } r.ID = id r.Name = aux.Name return nil } func (r *AccountRef) UnmarshalJSON(data []byte) error { var aux struct { ID json.RawMessage `json:"id"` Name string `json:"name,omitempty"` Platform string `json:"platform,omitempty"` Type string `json:"type,omitempty"` } if err := json.Unmarshal(data, &aux); err != nil { return err } id, err := decodeFlexibleID(aux.ID) if err != nil { return err } r.ID = id r.Name = aux.Name r.Platform = aux.Platform r.Type = aux.Type return nil } func (r *SubscriptionRef) UnmarshalJSON(data []byte) error { var aux struct { ID json.RawMessage `json:"id"` } if err := json.Unmarshal(data, &aux); err != nil { return err } id, err := decodeFlexibleID(aux.ID) if err != nil { return err } r.ID = id return nil }