mirror of
https://github.com/fish2018/pansou.git
synced 2025-11-25 03:14:59 +08:00
增加filter过滤
This commit is contained in:
16
README.md
16
README.md
@@ -404,6 +404,7 @@ curl -X POST http://localhost:8888/api/auth/logout
|
||||
| plugins | string[] | 否 | 指定搜索的插件列表,不指定则搜索全部插件 |
|
||||
| cloud_types | string[] | 否 | 指定返回的网盘类型列表,支持:baidu、aliyun、quark、tianyi、uc、mobile、115、pikpak、xunlei、123、magnet、ed2k,不指定则返回所有类型 |
|
||||
| ext | object | 否 | 扩展参数,用于传递给插件的自定义参数,如{"title_en":"English Title", "is_all":true} |
|
||||
| filter | object | 否 | 过滤配置,用于过滤返回结果。格式:{"include":["关键词1","关键词2"],"exclude":["排除词1","排除词2"]}。include为包含关键词列表(OR关系),exclude为排除关键词列表(AND关系) |
|
||||
|
||||
**GET请求参数**:
|
||||
|
||||
@@ -418,6 +419,7 @@ curl -X POST http://localhost:8888/api/auth/logout
|
||||
| plugins | string | 否 | 指定搜索的插件列表,使用英文逗号分隔多个插件名,不指定则搜索全部插件 |
|
||||
| cloud_types | string | 否 | 指定返回的网盘类型列表,使用英文逗号分隔多个类型,支持:baidu、aliyun、quark、tianyi、uc、mobile、115、pikpak、xunlei、123、magnet、ed2k,不指定则返回所有类型 |
|
||||
| ext | string | 否 | JSON格式的扩展参数,用于传递给插件的自定义参数,如{"title_en":"English Title", "is_all":true} |
|
||||
| filter | string | 否 | JSON格式的过滤配置,用于过滤返回结果。格式:{"include":["关键词1","关键词2"],"exclude":["排除词1","排除词2"]} |
|
||||
|
||||
**POST请求示例**:
|
||||
|
||||
@@ -448,6 +450,17 @@ curl -X POST http://localhost:8888/api/search \
|
||||
"kw": "速度与激情",
|
||||
"res": "merge"
|
||||
}'
|
||||
|
||||
# 使用过滤器(只返回包含“合集”或“全集”,且不包含“预告”的结果)
|
||||
curl -X POST http://localhost:8888/api/search \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"kw": "唐朝诡事录",
|
||||
"filter": {
|
||||
"include": ["合集", "全集"],
|
||||
"exclude": ["预告", "花絮"]
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
**GET请求示例**:
|
||||
@@ -459,6 +472,9 @@ curl "http://localhost:8888/api/search?kw=速度与激情&res=merge&src=tg"
|
||||
# 启用认证时(需要添加Authorization头)
|
||||
curl "http://localhost:8888/api/search?kw=速度与激情&res=merge" \
|
||||
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
||||
|
||||
# 使用过滤器(GET方式需要URL编码JSON)
|
||||
curl "http://localhost:8888/api/search?kw=唐朝诡事录&filter=%7B%22include%22%3A%5B%22合集%22%2C%22全集%22%5D%2C%22exclude%22%3A%5B%22预告%22%5D%7D"
|
||||
```
|
||||
|
||||
**成功响应**:
|
||||
|
||||
140
api/filter.go
Normal file
140
api/filter.go
Normal file
@@ -0,0 +1,140 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"pansou/model"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// applyResultFilter 应用过滤器到搜索响应
|
||||
func applyResultFilter(response model.SearchResponse, filter *model.FilterConfig, resultType string) model.SearchResponse {
|
||||
if filter == nil || (len(filter.Include) == 0 && len(filter.Exclude) == 0) {
|
||||
return response
|
||||
}
|
||||
|
||||
// 预处理关键词(转小写)
|
||||
includeKeywords := make([]string, len(filter.Include))
|
||||
for i, kw := range filter.Include {
|
||||
includeKeywords[i] = strings.ToLower(kw)
|
||||
}
|
||||
|
||||
excludeKeywords := make([]string, len(filter.Exclude))
|
||||
for i, kw := range filter.Exclude {
|
||||
excludeKeywords[i] = strings.ToLower(kw)
|
||||
}
|
||||
|
||||
// 根据结果类型决定过滤策略
|
||||
if resultType == "merged_by_type" || resultType == "" {
|
||||
// 过滤 merged_by_type 的 note 字段
|
||||
response.MergedByType = filterMergedByType(response.MergedByType, includeKeywords, excludeKeywords)
|
||||
|
||||
// 重新计算 total
|
||||
total := 0
|
||||
for _, links := range response.MergedByType {
|
||||
total += len(links)
|
||||
}
|
||||
response.Total = total
|
||||
} else if resultType == "all" || resultType == "results" {
|
||||
// 过滤 results 的 title 和 links 的 work_title
|
||||
response.Results = filterResults(response.Results, includeKeywords, excludeKeywords)
|
||||
response.Total = len(response.Results)
|
||||
|
||||
// 如果是 all 类型,也需要过滤 merged_by_type
|
||||
if resultType == "all" {
|
||||
response.MergedByType = filterMergedByType(response.MergedByType, includeKeywords, excludeKeywords)
|
||||
}
|
||||
}
|
||||
|
||||
return response
|
||||
}
|
||||
|
||||
// filterMergedByType 过滤 merged_by_type 中的链接
|
||||
func filterMergedByType(mergedLinks model.MergedLinks, includeKeywords, excludeKeywords []string) model.MergedLinks {
|
||||
if mergedLinks == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
filtered := make(model.MergedLinks)
|
||||
|
||||
for linkType, links := range mergedLinks {
|
||||
filteredLinks := make([]model.MergedLink, 0)
|
||||
|
||||
for _, link := range links {
|
||||
if matchFilter(link.Note, includeKeywords, excludeKeywords) {
|
||||
filteredLinks = append(filteredLinks, link)
|
||||
}
|
||||
}
|
||||
|
||||
// 只添加非空的类型
|
||||
if len(filteredLinks) > 0 {
|
||||
filtered[linkType] = filteredLinks
|
||||
}
|
||||
}
|
||||
|
||||
return filtered
|
||||
}
|
||||
|
||||
// filterResults 过滤 results 数组
|
||||
func filterResults(results []model.SearchResult, includeKeywords, excludeKeywords []string) []model.SearchResult {
|
||||
if results == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
filtered := make([]model.SearchResult, 0)
|
||||
|
||||
for _, result := range results {
|
||||
// 先检查 title 是否匹配
|
||||
if !matchFilter(result.Title, includeKeywords, excludeKeywords) {
|
||||
continue
|
||||
}
|
||||
|
||||
// title 匹配后,过滤 links 中的 work_title
|
||||
filteredLinks := make([]model.Link, 0)
|
||||
for _, link := range result.Links {
|
||||
// 如果 link 有 work_title,检查它;否则使用 result.Title
|
||||
checkText := link.WorkTitle
|
||||
if checkText == "" {
|
||||
checkText = result.Title
|
||||
}
|
||||
|
||||
if matchFilter(checkText, includeKeywords, excludeKeywords) {
|
||||
filteredLinks = append(filteredLinks, link)
|
||||
}
|
||||
}
|
||||
|
||||
// 只有有链接的结果才添加
|
||||
if len(filteredLinks) > 0 {
|
||||
result.Links = filteredLinks
|
||||
filtered = append(filtered, result)
|
||||
}
|
||||
}
|
||||
|
||||
return filtered
|
||||
}
|
||||
|
||||
// matchFilter 检查文本是否匹配过滤条件
|
||||
func matchFilter(text string, includeKeywords, excludeKeywords []string) bool {
|
||||
lowerText := strings.ToLower(text)
|
||||
|
||||
// 检查 exclude(任一匹配则排除)
|
||||
for _, kw := range excludeKeywords {
|
||||
if strings.Contains(lowerText, kw) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// 检查 include(如果有 include 列表,必须至少匹配一个)
|
||||
if len(includeKeywords) > 0 {
|
||||
matched := false
|
||||
for _, kw := range includeKeywords {
|
||||
if strings.Contains(lowerText, kw) {
|
||||
matched = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !matched {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
@@ -130,6 +130,17 @@ func SearchHandler(c *gin.Context) {
|
||||
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,
|
||||
@@ -141,6 +152,7 @@ func SearchHandler(c *gin.Context) {
|
||||
Plugins: plugins,
|
||||
CloudTypes: cloudTypes, // 添加cloud_types到请求中
|
||||
Ext: ext,
|
||||
Filter: filter,
|
||||
}
|
||||
} else {
|
||||
// POST方式:从请求体获取
|
||||
@@ -200,6 +212,11 @@ func SearchHandler(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// 应用过滤器
|
||||
if req.Filter != nil {
|
||||
result = applyResultFilter(result, req.Filter, req.ResultType)
|
||||
}
|
||||
|
||||
// 包装SearchResponse到标准响应格式中
|
||||
response := model.NewSuccessResponse(result)
|
||||
jsonData, _ := jsonutil.Marshal(response)
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
package model
|
||||
|
||||
// FilterConfig 过滤配置
|
||||
type FilterConfig struct {
|
||||
Include []string `json:"include,omitempty"` // 包含关键词列表(OR关系)
|
||||
Exclude []string `json:"exclude,omitempty"` // 排除关键词列表(AND关系)
|
||||
}
|
||||
|
||||
// SearchRequest 搜索请求参数
|
||||
type SearchRequest struct {
|
||||
Keyword string `json:"kw" binding:"required"` // 搜索关键词
|
||||
@@ -11,4 +17,5 @@ type SearchRequest struct {
|
||||
Plugins []string `json:"plugins"` // 指定搜索的插件列表,不指定则搜索全部插件
|
||||
Ext map[string]interface{} `json:"ext"` // 扩展参数,用于传递给插件的自定义参数
|
||||
CloudTypes []string `json:"cloud_types"` // 指定返回的网盘类型列表,不指定则返回所有类型
|
||||
Filter *FilterConfig `json:"filter,omitempty"` // 过滤配置,用于过滤返回结果
|
||||
}
|
||||
Reference in New Issue
Block a user