| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- package service
- import (
- "bytes"
- "encoding/json"
- "strconv"
- "strings"
- )
- type openAIRateLimitResetCreditDetailPayload struct {
- ID string `json:"id,omitempty"`
- CreditID string `json:"credit_id,omitempty"`
- CreditIDCamel string `json:"creditId,omitempty"`
- ExpiresAt string `json:"expires_at,omitempty"`
- ExpiresAtCamel string `json:"expiresAt,omitempty"`
- ResetType string `json:"reset_type,omitempty"`
- ResetTypeCamel string `json:"resetType,omitempty"`
- Status string `json:"status,omitempty"`
- }
- type openAIRateLimitResetCreditDetailsPayload struct {
- AvailableCount json.RawMessage `json:"available_count,omitempty"`
- AvailableCountCamel json.RawMessage `json:"availableCount,omitempty"`
- Credits json.RawMessage `json:"credits,omitempty"`
- RateLimitResetCredits json.RawMessage `json:"rate_limit_reset_credits,omitempty"`
- Items json.RawMessage `json:"items,omitempty"`
- Data json.RawMessage `json:"data,omitempty"`
- }
- type openAIRateLimitResetCreditDetails struct {
- AvailableCount *int
- AvailableCreditCount int
- CreditListPresent bool
- Credits []OpenAIRateLimitResetCreditDetail
- AutoResetCandidates []openAIAutoResetCreditCandidate
- }
- // openAIAutoResetCreditCandidate 仅在服务内部流转。上游卡 ID 不进入 API DTO、
- // 账号 extra 或日志,避免管理端响应扩大敏感标识暴露面。
- type openAIAutoResetCreditCandidate struct {
- ID string
- ExpiresAt string
- }
- func parseOpenAIRateLimitResetCreditDetails(body []byte) (openAIRateLimitResetCreditDetails, error) {
- trimmed := bytes.TrimSpace(body)
- if len(trimmed) == 0 {
- return openAIRateLimitResetCreditDetails{}, nil
- }
- var rawCredits []*openAIRateLimitResetCreditDetailPayload
- var availableCount *int
- var creditListPresent bool
- if trimmed[0] == '[' {
- if err := json.Unmarshal(trimmed, &rawCredits); err != nil {
- return openAIRateLimitResetCreditDetails{}, err
- }
- creditListPresent = true
- } else {
- var payload openAIRateLimitResetCreditDetailsPayload
- if err := json.Unmarshal(trimmed, &payload); err != nil {
- return openAIRateLimitResetCreditDetails{}, err
- }
- availableCount = parseOpenAIResetCreditAvailableCount(payload.AvailableCount, payload.AvailableCountCamel)
- var err error
- rawCredits, creditListPresent, err = firstPresentResetCreditPayload(
- payload.Credits,
- payload.RateLimitResetCredits,
- payload.Items,
- payload.Data,
- )
- if err != nil {
- return openAIRateLimitResetCreditDetails{AvailableCount: availableCount}, err
- }
- }
- credits := make([]OpenAIRateLimitResetCreditDetail, 0, len(rawCredits))
- autoResetCandidates := make([]openAIAutoResetCreditCandidate, 0, len(rawCredits))
- availableCreditCount := 0
- for _, raw := range rawCredits {
- if raw == nil {
- continue
- }
- resetType := strings.TrimSpace(raw.ResetType)
- if resetType == "" {
- resetType = strings.TrimSpace(raw.ResetTypeCamel)
- }
- if resetType != "" && !strings.EqualFold(resetType, "codex_rate_limits") {
- continue
- }
- if status := strings.TrimSpace(raw.Status); status != "" && !strings.EqualFold(status, "available") {
- continue
- }
- availableCreditCount++
- expiresAt := strings.TrimSpace(raw.ExpiresAt)
- if expiresAt == "" {
- expiresAt = strings.TrimSpace(raw.ExpiresAtCamel)
- }
- if expiresAt == "" {
- continue
- }
- credits = append(credits, OpenAIRateLimitResetCreditDetail{ExpiresAt: expiresAt})
- creditID := strings.TrimSpace(raw.ID)
- if creditID == "" {
- creditID = strings.TrimSpace(raw.CreditID)
- }
- if creditID == "" {
- creditID = strings.TrimSpace(raw.CreditIDCamel)
- }
- autoResetCandidates = append(autoResetCandidates, openAIAutoResetCreditCandidate{
- ID: creditID,
- ExpiresAt: expiresAt,
- })
- }
- return openAIRateLimitResetCreditDetails{
- AvailableCount: availableCount,
- AvailableCreditCount: availableCreditCount,
- CreditListPresent: creditListPresent,
- Credits: credits,
- AutoResetCandidates: autoResetCandidates,
- }, nil
- }
- func parseOpenAIResetCreditAvailableCount(values ...json.RawMessage) *int {
- for _, value := range values {
- trimmed := bytes.TrimSpace(value)
- if len(trimmed) == 0 || bytes.Equal(trimmed, []byte("null")) {
- continue
- }
- var count int
- if trimmed[0] == '"' {
- var text string
- if err := json.Unmarshal(trimmed, &text); err != nil {
- continue
- }
- parsed, err := strconv.Atoi(strings.TrimSpace(text))
- if err != nil {
- continue
- }
- count = parsed
- } else if err := json.Unmarshal(trimmed, &count); err != nil {
- continue
- }
- if count >= 0 {
- return &count
- }
- }
- return nil
- }
- func firstPresentResetCreditPayload(values ...json.RawMessage) ([]*openAIRateLimitResetCreditDetailPayload, bool, error) {
- for _, value := range values {
- trimmed := bytes.TrimSpace(value)
- if len(trimmed) == 0 || bytes.Equal(trimmed, []byte("null")) {
- continue
- }
- var credits []*openAIRateLimitResetCreditDetailPayload
- if err := json.Unmarshal(trimmed, &credits); err != nil {
- return nil, false, err
- }
- return credits, true, nil
- }
- return nil, false, nil
- }
|