feat: sync deployed v1.0.0-rc.38-custom.42

Sync production source including routing, billing, Astra detection and public uptime. Update custom build instructions and license packaging.
This commit is contained in:
cneicy committed 2026-09-26 04:49:11 +08:00
1 parent aa6c3f50f4
commit ceddfd3d6b
828 files changed
+122253 -13702

No files matched your search

+53 -7
View File
@@ -18,10 +18,13 @@ import (
"github.com/QuantumNous/new-api/setting/model_setting"
"github.com/gin-gonic/gin"
"github.com/tidwall/sjson"
)
func ImageHelper(c *gin.Context, info *relaycommon.RelayInfo) (newAPIError *types.NewAPIError) {
info.InitChannelMeta(c)
info.BillingImageCount = nil
info.ImageRequestCount = 0
imageReq, ok := info.Request.(*dto.ImageRequest)
if !ok {
@@ -43,15 +46,28 @@ func ImageHelper(c *gin.Context, info *relaycommon.RelayInfo) (newAPIError *type
return types.NewError(fmt.Errorf("invalid api type: %d", info.ApiType), types.ErrorCodeInvalidApiType, types.ErrOptionWithSkipRetry())
}
adaptor.Init(info)
imageCount, err := request.ImageCount(info.ChannelType == constant.ChannelTypeAli)
if err != nil {
return types.NewErrorWithStatusCode(err, types.ErrorCodeInvalidRequest, http.StatusBadRequest, types.ErrOptionWithSkipRetry())
}
promptExtend := request.BillingParameters != nil && request.BillingParameters.PromptExtend != nil && *request.BillingParameters.PromptExtend
var requestBody io.Reader
var jsonData []byte
if model_setting.GetGlobalSettings().PassThroughRequestEnabled || info.ChannelSetting.PassThroughBodyEnabled {
storage, err := common.GetBodyStorage(c)
if err != nil {
return types.NewErrorWithStatusCode(err, types.ErrorCodeReadRequestBodyFailed, http.StatusBadRequest, types.ErrOptionWithSkipRetry())
}
requestBody = common.NewReplayableBodyReader(storage)
if strings.Contains(c.Request.Header.Get("Content-Type"), "multipart/form-data") {
requestBody = common.NewReplayableBodyReader(storage)
} else {
jsonData, err = storage.Bytes()
if err != nil {
return types.NewErrorWithStatusCode(err, types.ErrorCodeReadRequestBodyFailed, http.StatusBadRequest, types.ErrOptionWithSkipRetry())
}
}
} else {
convertedRequest, err := adaptor.ConvertImageRequest(c, info, *request)
if err != nil {
@@ -63,7 +79,7 @@ func ImageHelper(c *gin.Context, info *relaycommon.RelayInfo) (newAPIError *type
case *bytes.Buffer:
requestBody = convertedRequest.(io.Reader)
default:
jsonData, err := common.Marshal(convertedRequest)
jsonData, err = common.Marshal(convertedRequest)
if err != nil {
return types.NewError(err, types.ErrorCodeConvertRequestFailed, types.ErrOptionWithSkipRetry())
}
@@ -76,15 +92,45 @@ func ImageHelper(c *gin.Context, info *relaycommon.RelayInfo) (newAPIError *type
}
}
logger.LogDebug(c, "image request body: %s", jsonData)
body, closer, err := relaycommon.NewOutboundJSONBody(jsonData)
}
}
if jsonData != nil {
// This is a different trust boundary from ingress: channel overrides
// and pass-through bodies can change the quantity actually submitted.
var outbound struct {
N *uint `json:"n"`
Parameters *dto.ImageBillingParameters `json:"parameters"`
}
if err := common.Unmarshal(jsonData, &outbound); err != nil {
return types.NewErrorWithStatusCode(fmt.Errorf("invalid image billing parameters: %w", err), types.ErrorCodeInvalidRequest, http.StatusBadRequest, types.ErrOptionWithSkipRetry())
}
quantityRequest := dto.ImageRequest{N: outbound.N, BillingParameters: outbound.Parameters}
if quantityRequest.N == nil {
quantityRequest.N = common.GetPointer(uint(imageCount))
}
imageCount, err = quantityRequest.ImageCount(info.ChannelType == constant.ChannelTypeAli)
if err != nil {
return types.NewErrorWithStatusCode(err, types.ErrorCodeInvalidRequest, http.StatusBadRequest, types.ErrOptionWithSkipRetry())
}
promptExtend = outbound.Parameters != nil && outbound.Parameters.PromptExtend != nil && *outbound.Parameters.PromptExtend
if info.ChannelType == constant.ChannelTypeAli {
// Always send the same explicit quantity that is reserved, including
// when an empty parameters object accompanies a top-level n.
jsonData, err = sjson.SetBytes(jsonData, "parameters.n", imageCount)
if err != nil {
return types.NewError(err, types.ErrorCodeConvertRequestFailed, types.ErrOptionWithSkipRetry())
}
defer closer.Close()
jsonData = nil
requestBody = body
}
logger.LogDebug(c, "image request body: %s", jsonData)
body, closer, err := relaycommon.NewOutboundJSONBody(jsonData)
if err != nil {
return types.NewError(err, types.ErrorCodeConvertRequestFailed, types.ErrOptionWithSkipRetry())
}
defer closer.Close()
requestBody = body
}
if billingErr := service.PrepareImageBillingForRequest(c, info, imageCount, promptExtend); billingErr != nil {
return billingErr
}
statusCodeMappingStr := c.GetString("status_code_mapping")