Spaces:
Paused
Paused
| package api | |
| import ( | |
| // "fmt" | |
| "net/http" | |
| // "os" | |
| "github.com/gin-gonic/gin" | |
| "pansou/config" | |
| "pansou/model" | |
| "pansou/service" | |
| jsonutil "pansou/util/json" | |
| "pansou/util" | |
| "strings" | |
| ) | |
| // 保存搜索服务的实例 | |
| var searchService *service.SearchService | |
| // SetSearchService 设置搜索服务实例 | |
| func SetSearchService(service *service.SearchService) { | |
| searchService = service | |
| } | |
| // SearchHandler 搜索处理函数 | |
| func SearchHandler(c *gin.Context) { | |
| var req model.SearchRequest | |
| var err error | |
| // 根据请求方法不同处理参数 | |
| if c.Request.Method == http.MethodGet { | |
| // GET方式:从URL参数获取 | |
| // 获取keyword,必填参数 | |
| keyword := c.Query("kw") | |
| // 处理channels参数,支持逗号分隔 | |
| channelsStr := c.Query("channels") | |
| var channels []string | |
| // 只有当参数非空时才处理 | |
| if channelsStr != "" && channelsStr != " " { | |
| parts := strings.Split(channelsStr, ",") | |
| for _, part := range parts { | |
| trimmed := strings.TrimSpace(part) | |
| if trimmed != "" { | |
| channels = append(channels, trimmed) | |
| } | |
| } | |
| } | |
| // 处理并发数 | |
| concurrency := 0 | |
| concStr := c.Query("conc") | |
| if concStr != "" && concStr != " " { | |
| concurrency = util.StringToInt(concStr) | |
| } | |
| // 处理强制刷新 | |
| forceRefresh := false | |
| refreshStr := c.Query("refresh") | |
| if refreshStr != "" && refreshStr != " " && refreshStr == "true" { | |
| forceRefresh = true | |
| } | |
| // 处理结果类型和来源类型 | |
| resultType := c.Query("res") | |
| if resultType == "" || resultType == " " { | |
| resultType = "merge" // 直接设置为默认值merge | |
| } | |
| sourceType := c.Query("src") | |
| if sourceType == "" || sourceType == " " { | |
| sourceType = "all" // 直接设置为默认值all | |
| } | |
| // 处理plugins参数,支持逗号分隔 | |
| var plugins []string | |
| // 检查请求中是否存在plugins参数 | |
| if c.Request.URL.Query().Has("plugins") { | |
| pluginsStr := c.Query("plugins") | |
| // 判断参数是否非空 | |
| if pluginsStr != "" && pluginsStr != " " { | |
| parts := strings.Split(pluginsStr, ",") | |
| for _, part := range parts { | |
| trimmed := strings.TrimSpace(part) | |
| if trimmed != "" { | |
| plugins = append(plugins, trimmed) | |
| } | |
| } | |
| } | |
| } else { | |
| // 如果请求中不存在plugins参数,设置为nil | |
| plugins = nil | |
| } | |
| // 处理cloud_types参数,支持逗号分隔 | |
| var cloudTypes []string | |
| // 检查请求中是否存在cloud_types参数 | |
| if c.Request.URL.Query().Has("cloud_types") { | |
| cloudTypesStr := c.Query("cloud_types") | |
| // 判断参数是否非空 | |
| if cloudTypesStr != "" && cloudTypesStr != " " { | |
| parts := strings.Split(cloudTypesStr, ",") | |
| for _, part := range parts { | |
| trimmed := strings.TrimSpace(part) | |
| if trimmed != "" { | |
| cloudTypes = append(cloudTypes, trimmed) | |
| } | |
| } | |
| } | |
| } else { | |
| // 如果请求中不存在cloud_types参数,设置为nil | |
| cloudTypes = nil | |
| } | |
| // 处理ext参数,JSON格式 | |
| var ext map[string]interface{} | |
| extStr := c.Query("ext") | |
| if extStr != "" && extStr != " " { | |
| // 处理特殊情况:ext={} | |
| if extStr == "{}" { | |
| ext = make(map[string]interface{}) | |
| } else { | |
| if err := jsonutil.Unmarshal([]byte(extStr), &ext); err != nil { | |
| c.JSON(http.StatusBadRequest, model.NewErrorResponse(400, "无效的ext参数格式: "+err.Error())) | |
| return | |
| } | |
| } | |
| } | |
| // 确保ext不为nil | |
| if ext == nil { | |
| ext = make(map[string]interface{}) | |
| } | |
| // 处理filter参数,JSON格式 | |
| var filter *model.FilterConfig | |
| filterStr := c.Query("filter") | |
| if filterStr != "" && filterStr != " " { | |
| filter = &model.FilterConfig{} | |
| if err := jsonutil.Unmarshal([]byte(filterStr), filter); err != nil { | |
| c.JSON(http.StatusBadRequest, model.NewErrorResponse(400, "无效的filter参数格式: "+err.Error())) | |
| return | |
| } | |
| } | |
| req = model.SearchRequest{ | |
| Keyword: keyword, | |
| Channels: channels, | |
| Concurrency: concurrency, | |
| ForceRefresh: forceRefresh, | |
| ResultType: resultType, | |
| SourceType: sourceType, | |
| Plugins: plugins, | |
| CloudTypes: cloudTypes, // 添加cloud_types到请求中 | |
| Ext: ext, | |
| Filter: filter, | |
| } | |
| } else { | |
| // POST方式:从请求体获取 | |
| data, err := c.GetRawData() | |
| if err != nil { | |
| c.JSON(http.StatusBadRequest, model.NewErrorResponse(400, "读取请求数据失败: "+err.Error())) | |
| return | |
| } | |
| if err := jsonutil.Unmarshal(data, &req); err != nil { | |
| c.JSON(http.StatusBadRequest, model.NewErrorResponse(400, "无效的请求参数: "+err.Error())) | |
| return | |
| } | |
| } | |
| // 检查并设置默认值 | |
| if len(req.Channels) == 0 { | |
| req.Channels = config.AppConfig.DefaultChannels | |
| } | |
| // 如果未指定结果类型,默认返回merge并转换为merged_by_type | |
| if req.ResultType == "" { | |
| req.ResultType = "merged_by_type" | |
| } else if req.ResultType == "merge" { | |
| // 将merge转换为merged_by_type,以兼容内部处理 | |
| req.ResultType = "merged_by_type" | |
| } | |
| // 如果未指定数据来源类型,默认为全部 | |
| if req.SourceType == "" { | |
| req.SourceType = "all" | |
| } | |
| // 参数互斥逻辑:当src=tg时忽略plugins参数,当src=plugin时忽略channels参数 | |
| if req.SourceType == "tg" { | |
| req.Plugins = nil // 忽略plugins参数 | |
| } else if req.SourceType == "plugin" { | |
| req.Channels = nil // 忽略channels参数 | |
| } else if req.SourceType == "all" { | |
| // 对于all类型,如果plugins为空或不存在,统一设为nil | |
| if req.Plugins == nil || len(req.Plugins) == 0 { | |
| req.Plugins = nil | |
| } | |
| } | |
| // 可选:启用调试输出(生产环境建议注释掉) | |
| // fmt.Printf("🔧 [调试] 搜索参数: keyword=%s, channels=%v, concurrency=%d, refresh=%v, resultType=%s, sourceType=%s, plugins=%v, cloudTypes=%v, ext=%v\n", | |
| // req.Keyword, req.Channels, req.Concurrency, req.ForceRefresh, req.ResultType, req.SourceType, req.Plugins, req.CloudTypes, req.Ext) | |
| // 执行搜索 | |
| result, err := searchService.Search(req.Keyword, req.Channels, req.Concurrency, req.ForceRefresh, req.ResultType, req.SourceType, req.Plugins, req.CloudTypes, req.Ext) | |
| if err != nil { | |
| response := model.NewErrorResponse(500, "搜索失败: "+err.Error()) | |
| jsonData, _ := jsonutil.Marshal(response) | |
| c.Data(http.StatusInternalServerError, "application/json", jsonData) | |
| return | |
| } | |
| // 应用过滤器 | |
| if req.Filter != nil { | |
| result = applyResultFilter(result, req.Filter, req.ResultType) | |
| } | |
| // 包装SearchResponse到标准响应格式中 | |
| response := model.NewSuccessResponse(result) | |
| jsonData, _ := jsonutil.Marshal(response) | |
| c.Data(http.StatusOK, "application/json", jsonData) | |
| } |