Files
sub2api-cn-relay-manager/internal/host/sub2api/flexible_id.go

236 lines
5.7 KiB
Go

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
}