From aa35d8db69b50d6401550bd34b6f37ef5863acd0 Mon Sep 17 00:00:00 2001 From: CaIon Date: Tue, 14 Oct 2025 23:03:17 +0800 Subject: [PATCH] refactor: update ConvertToOpenAIVideo method to return byte array and improve error handling --- controller/task_video.go | 10 ++++++++-- dto/openai_video.go | 2 +- relay/channel/adapter.go | 2 +- relay/channel/task/jimeng/adaptor.go | 6 ++++-- relay/channel/task/kling/adaptor.go | 7 ++++--- relay/channel/task/sora/adaptor.go | 14 ++++---------- relay/channel/task/vidu/adaptor.go | 6 ++++-- relay/common/relay_info.go | 7 +++++++ relay/relay_task.go | 4 ++-- 9 files changed, 35 insertions(+), 23 deletions(-) diff --git a/controller/task_video.go b/controller/task_video.go index cc99f78d3..a9282aa01 100644 --- a/controller/task_video.go +++ b/controller/task_video.go @@ -88,10 +88,13 @@ func updateVideoSingleTask(ctx context.Context, adaptor channel.TaskAdaptor, cha return fmt.Errorf("readAll failed for task %s: %w", taskId, err) } + logger.LogDebug(ctx, fmt.Sprintf("UpdateVideoSingleTask response: %s", string(responseBody))) + taskResult := &relaycommon.TaskInfo{} // try parse as New API response format var responseItems dto.TaskResponse[model.Task] - if err = json.Unmarshal(responseBody, &responseItems); err == nil && responseItems.IsSuccess() { + if err = common.Unmarshal(responseBody, &responseItems); err == nil && responseItems.IsSuccess() { + logger.LogDebug(ctx, fmt.Sprintf("UpdateVideoSingleTask parsed as new api response format: %+v", responseItems)) t := responseItems.Data taskResult.TaskID = t.TaskID taskResult.Status = string(t.Status) @@ -105,9 +108,12 @@ func updateVideoSingleTask(ctx context.Context, adaptor channel.TaskAdaptor, cha task.Data = redactVideoResponseBody(responseBody) } + logger.LogDebug(ctx, fmt.Sprintf("UpdateVideoSingleTask taskResult: %+v", taskResult)) + now := time.Now().Unix() if taskResult.Status == "" { - return fmt.Errorf("task %s status is empty", taskId) + //return fmt.Errorf("task %s status is empty", taskId) + taskResult = relaycommon.FailTaskInfo("upstream returned empty status") } task.Status = model.TaskStatus(taskResult.Status) switch taskResult.Status { diff --git a/dto/openai_video.go b/dto/openai_video.go index bee64c31f..051769b98 100644 --- a/dto/openai_video.go +++ b/dto/openai_video.go @@ -27,7 +27,7 @@ type OpenAIVideo struct { Size string `json:"size,omitempty"` RemixedFromVideoID string `json:"remixed_from_video_id,omitempty"` Error *OpenAIVideoError `json:"error,omitempty"` - Metadata map[string]any `json:"metadata,omitempty"` + Metadata map[string]any `json:"meta_data,omitempty"` } func (m *OpenAIVideo) SetProgressStr(progress string) { diff --git a/relay/channel/adapter.go b/relay/channel/adapter.go index 7431a0646..7f8faf22d 100644 --- a/relay/channel/adapter.go +++ b/relay/channel/adapter.go @@ -53,5 +53,5 @@ type TaskAdaptor interface { } type OpenAIVideoConverter interface { - ConvertToOpenAIVideo(originTask *model.Task) (*dto.OpenAIVideo, error) + ConvertToOpenAIVideo(originTask *model.Task) ([]byte, error) } diff --git a/relay/channel/task/jimeng/adaptor.go b/relay/channel/task/jimeng/adaptor.go index 01b51891e..f47143d8a 100644 --- a/relay/channel/task/jimeng/adaptor.go +++ b/relay/channel/task/jimeng/adaptor.go @@ -15,6 +15,7 @@ import ( "strings" "time" + "github.com/QuantumNous/new-api/common" "github.com/QuantumNous/new-api/model" "github.com/gin-gonic/gin" @@ -446,7 +447,7 @@ func (a *TaskAdaptor) ParseTaskResult(respBody []byte) (*relaycommon.TaskInfo, e return &taskResult, nil } -func (a *TaskAdaptor) ConvertToOpenAIVideo(originTask *model.Task) (*dto.OpenAIVideo, error) { +func (a *TaskAdaptor) ConvertToOpenAIVideo(originTask *model.Task) ([]byte, error) { var jimengResp responseTask if err := json.Unmarshal(originTask.Data, &jimengResp); err != nil { return nil, errors.Wrap(err, "unmarshal jimeng task data failed") @@ -467,7 +468,8 @@ func (a *TaskAdaptor) ConvertToOpenAIVideo(originTask *model.Task) (*dto.OpenAIV } } - return openAIVideo, nil + jsonData, _ := common.Marshal(openAIVideo) + return jsonData, nil } func isNewAPIRelay(apiKey string) bool { diff --git a/relay/channel/task/kling/adaptor.go b/relay/channel/task/kling/adaptor.go index 81db82484..c1bbd9d59 100644 --- a/relay/channel/task/kling/adaptor.go +++ b/relay/channel/task/kling/adaptor.go @@ -9,6 +9,7 @@ import ( "strings" "time" + "github.com/QuantumNous/new-api/common" "github.com/QuantumNous/new-api/model" "github.com/samber/lo" @@ -367,7 +368,7 @@ func isNewAPIRelay(apiKey string) bool { return strings.HasPrefix(apiKey, "sk-") } -func (a *TaskAdaptor) ConvertToOpenAIVideo(originTask *model.Task) (*dto.OpenAIVideo, error) { +func (a *TaskAdaptor) ConvertToOpenAIVideo(originTask *model.Task) ([]byte, error) { var klingResp responsePayload if err := json.Unmarshal(originTask.Data, &klingResp); err != nil { return nil, errors.Wrap(err, "unmarshal kling task data failed") @@ -396,6 +397,6 @@ func (a *TaskAdaptor) ConvertToOpenAIVideo(originTask *model.Task) (*dto.OpenAIV Code: fmt.Sprintf("%d", klingResp.Code), } } - - return openAIVideo, nil + jsonData, _ := common.Marshal(openAIVideo) + return jsonData, nil } diff --git a/relay/channel/task/sora/adaptor.go b/relay/channel/task/sora/adaptor.go index 5f16fbb03..17aec18f0 100644 --- a/relay/channel/task/sora/adaptor.go +++ b/relay/channel/task/sora/adaptor.go @@ -2,7 +2,6 @@ package sora import ( "bytes" - "encoding/json" "fmt" "io" "net/http" @@ -107,7 +106,7 @@ func (a *TaskAdaptor) DoResponse(c *gin.Context, resp *http.Response, _ *relayco // Parse Sora response var dResp responseTask - if err := json.Unmarshal(responseBody, &dResp); err != nil { + if err := common.Unmarshal(responseBody, &dResp); err != nil { taskErr = service.TaskErrorWrapper(errors.Wrapf(err, "body: %s", responseBody), "unmarshal_response_body_failed", http.StatusInternalServerError) return } @@ -154,7 +153,7 @@ func (a *TaskAdaptor) GetChannelName() string { func (a *TaskAdaptor) ParseTaskResult(respBody []byte) (*relaycommon.TaskInfo, error) { resTask := responseTask{} - if err := json.Unmarshal(respBody, &resTask); err != nil { + if err := common.Unmarshal(respBody, &resTask); err != nil { return nil, errors.Wrap(err, "unmarshal task result failed") } @@ -186,11 +185,6 @@ func (a *TaskAdaptor) ParseTaskResult(respBody []byte) (*relaycommon.TaskInfo, e return &taskResult, nil } -func (a *TaskAdaptor) ConvertToOpenAIVideo(task *model.Task) (*dto.OpenAIVideo, error) { - openAIVideo := &dto.OpenAIVideo{} - err := json.Unmarshal(task.Data, openAIVideo) - if err != nil { - return nil, errors.Wrap(err, "unmarshal to OpenAIVideo failed") - } - return openAIVideo, nil +func (a *TaskAdaptor) ConvertToOpenAIVideo(task *model.Task) ([]byte, error) { + return task.Data, nil } diff --git a/relay/channel/task/vidu/adaptor.go b/relay/channel/task/vidu/adaptor.go index b3108a245..7ccac2ff2 100644 --- a/relay/channel/task/vidu/adaptor.go +++ b/relay/channel/task/vidu/adaptor.go @@ -8,6 +8,7 @@ import ( "net/http" "time" + "github.com/QuantumNous/new-api/common" "github.com/gin-gonic/gin" "github.com/QuantumNous/new-api/constant" @@ -263,7 +264,7 @@ func (a *TaskAdaptor) ParseTaskResult(respBody []byte) (*relaycommon.TaskInfo, e return taskInfo, nil } -func (a *TaskAdaptor) ConvertToOpenAIVideo(originTask *model.Task) (*dto.OpenAIVideo, error) { +func (a *TaskAdaptor) ConvertToOpenAIVideo(originTask *model.Task) ([]byte, error) { var viduResp taskResultResponse if err := json.Unmarshal(originTask.Data, &viduResp); err != nil { return nil, errors.Wrap(err, "unmarshal vidu task data failed") @@ -287,5 +288,6 @@ func (a *TaskAdaptor) ConvertToOpenAIVideo(originTask *model.Task) (*dto.OpenAIV } } - return openAIVideo, nil + jsonData, _ := common.Marshal(openAIVideo) + return jsonData, nil } diff --git a/relay/common/relay_info.go b/relay/common/relay_info.go index c7c73980f..a23e863b6 100644 --- a/relay/common/relay_info.go +++ b/relay/common/relay_info.go @@ -512,6 +512,13 @@ type TaskInfo struct { TotalTokens int `json:"total_tokens,omitempty"` // 用于按倍率计费 } +func FailTaskInfo(reason string) *TaskInfo { + return &TaskInfo{ + Status: "FAILURE", + Reason: reason, + } +} + // RemoveDisabledFields 从请求 JSON 数据中移除渠道设置中禁用的字段 // service_tier: 服务层级字段,可能导致额外计费(OpenAI、Claude、Responses API 支持) // store: 数据存储授权字段,涉及用户隐私(仅 OpenAI、Responses API 支持,默认允许透传,禁用后可能导致 Codex 无法使用) diff --git a/relay/relay_task.go b/relay/relay_task.go index bf20f5bbd..7d2c8b5dc 100644 --- a/relay/relay_task.go +++ b/relay/relay_task.go @@ -397,12 +397,12 @@ func videoFetchByIDRespBodyBuilder(c *gin.Context) (respBody []byte, taskResp *d return } if converter, ok := adaptor.(channel.OpenAIVideoConverter); ok { - openAIVideo, err := converter.ConvertToOpenAIVideo(originTask) + openAIVideoData, err := converter.ConvertToOpenAIVideo(originTask) if err != nil { taskResp = service.TaskErrorWrapper(err, "convert_to_openai_video_failed", http.StatusInternalServerError) return } - respBody, _ = json.Marshal(openAIVideo) + respBody = openAIVideoData return } taskResp = service.TaskErrorWrapperLocal(errors.New(fmt.Sprintf("not_implemented:%s", originTask.Platform)), "not_implemented", http.StatusNotImplemented)