package orchestration import ( "encoding/json" "errors" "net/url" "git.nianxx.cn/wangxuming/NianAIGC/backend/internal/jobs" "git.nianxx.cn/wangxuming/NianAIGC/backend/internal/providers" ) // ResolveProviderOutputURLs extracts only documented provider output fields; // it does not recursively accept arbitrary strings from response payloads. func ResolveProviderOutputURLs(job jobs.Job) ([]string, error) { var root map[string]any if len(job.ResponsePayload) == 0 || json.Unmarshal(job.ResponsePayload, &root) != nil { return nil, errors.New("resolve generation outputs") } var persisted providers.HTTPResult if json.Unmarshal(job.ResponsePayload, &persisted) == nil && len(persisted.OutputURLs) > 0 { seen := map[string]bool{} result := []string{} for _, outputURL := range persisted.OutputURLs { collectOutputURLs(outputURL, seen, &result) } if len(result) > 0 { return result, nil } } candidates := []any{} data := objectMap(root["data"]) output := objectMap(root["output"]) content := objectMap(root["content"]) dataContent := objectMap(data["content"]) for _, object := range []map[string]any{root, data, output, content, dataContent} { for _, key := range []string{"image_urls", "images", "results", "choices", "outputs", "video_url", "url"} { candidates = append(candidates, object[key]) } } seen := map[string]bool{} result := []string{} for _, candidate := range candidates { collectOutputURLs(candidate, seen, &result) } if len(result) == 0 { return nil, errors.New("resolve generation outputs") } return result, nil } func collectOutputURLs(value any, seen map[string]bool, result *[]string) { switch typed := value.(type) { case string: parsed, err := url.Parse(typed) if err == nil && (parsed.Scheme == "http" || parsed.Scheme == "https") && parsed.Host != "" && !seen[typed] { seen[typed] = true *result = append(*result, typed) } case []any: for _, item := range typed { collectOutputURLs(item, seen, result) } case map[string]any: for _, key := range []string{"url", "image_url", "video_url"} { collectOutputURLs(typed[key], seen, result) } } } func objectMap(value any) map[string]any { object, _ := value.(map[string]any) return object }