text字段筛选
This commit is contained in:
		
							
								
								
									
										9
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								Makefile
									
									
									
									
									
								
							@@ -28,3 +28,12 @@ service:
 | 
				
			|||||||
	sudo cp webp.service /etc/systemd/system/webp.service
 | 
						sudo cp webp.service /etc/systemd/system/webp.service
 | 
				
			||||||
	sudo systemctl enable webp
 | 
						sudo systemctl enable webp
 | 
				
			||||||
	sudo cp webp.logrotate /etc/logrotate.d/webp
 | 
						sudo cp webp.logrotate /etc/logrotate.d/webp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 安装 zinc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 安装 gorse
 | 
				
			||||||
 | 
					gorse:
 | 
				
			||||||
 | 
						export GORSE_DASHBOARD_USER="gorse"
 | 
				
			||||||
 | 
						export GORSE_DASHBOARD_PASS="gorse"
 | 
				
			||||||
 | 
						curl -fsSL https://gorse.io/playground | bash
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										18
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								README.md
									
									
									
									
									
								
							@@ -1,11 +1,29 @@
 | 
				
			|||||||
# webp
 | 
					# webp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- [ ] 原始图像
 | 
				
			||||||
 | 
					- [ ] 缩略缓存
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- [ ] 不同类型的用途(文章, 截图, 头像)
 | 
				
			||||||
 | 
					- [ ] 增量备份
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cdn(img.gameui.net) -> main -> img
 | 
				
			||||||
 | 
					/articles/{id}/{hash}
 | 
				
			||||||
 | 
					/users/{id}/{hash}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					UPDATE web_images SET description = '' WHERE description IS NULL;
 | 
				
			||||||
 | 
					ALTER TABLE web_images MODIFY description VARCHAR(255) DEFAULT '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- [ ] 解析 cdn.gameui.net 到 cdn 服务, 并将 cdn 回源指向 def.gameui.net 其解析到新服务器
 | 
				
			||||||
 | 
					- [ ] 支持带参数下载指定尺寸图像
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- [x] 提供webp生成服务
 | 
					- [x] 提供webp生成服务
 | 
				
			||||||
- [x] 提供流媒体服务
 | 
					- [x] 提供流媒体服务
 | 
				
			||||||
  - [x] 点击播放之前不加载视频(减少流量消耗)
 | 
					  - [x] 点击播放之前不加载视频(减少流量消耗)
 | 
				
			||||||
  - [x] 使用封面图片替代加载视屏第一帧
 | 
					  - [x] 使用封面图片替代加载视屏第一帧
 | 
				
			||||||
- [x] GraphQL 风格API
 | 
					- [x] GraphQL 风格API
 | 
				
			||||||
  - [ ] 列表翻页
 | 
					  - [ ] 列表翻页
 | 
				
			||||||
 | 
					  - [ ] OCR 查询支持
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```javascript
 | 
					```javascript
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,7 @@ package api
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"log"
 | 
						"log"
 | 
				
			||||||
 | 
						"reflect"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"git.satori.love/gameui/webp/models"
 | 
						"git.satori.love/gameui/webp/models"
 | 
				
			||||||
@@ -12,6 +13,39 @@ import (
 | 
				
			|||||||
	"github.com/mitchellh/mapstructure"
 | 
						"github.com/mitchellh/mapstructure"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 自动生成 GraphQL 类型的函数
 | 
				
			||||||
 | 
					func generateGraphQLType(model interface{}) (*graphql.Object, error) {
 | 
				
			||||||
 | 
						modelType := reflect.TypeOf(model)
 | 
				
			||||||
 | 
						if modelType.Kind() != reflect.Struct {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("model must be a struct")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fields := graphql.Fields{}
 | 
				
			||||||
 | 
						for i := 0; i < modelType.NumField(); i++ {
 | 
				
			||||||
 | 
							field := modelType.Field(i)
 | 
				
			||||||
 | 
							fieldType := graphql.String // 默认使用字符串类型
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// 这里可以根据需要添加更多类型映射
 | 
				
			||||||
 | 
							switch field.Type.Kind() {
 | 
				
			||||||
 | 
							case reflect.String:
 | 
				
			||||||
 | 
								fieldType = graphql.String
 | 
				
			||||||
 | 
							case reflect.Int:
 | 
				
			||||||
 | 
								fieldType = graphql.Int
 | 
				
			||||||
 | 
							case reflect.Bool:
 | 
				
			||||||
 | 
								fieldType = graphql.Boolean
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							fields[field.Name] = &graphql.Field{
 | 
				
			||||||
 | 
								Type: fieldType,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return graphql.NewObject(graphql.ObjectConfig{
 | 
				
			||||||
 | 
							Name:   modelType.Name(),
 | 
				
			||||||
 | 
							Fields: fields,
 | 
				
			||||||
 | 
						}), nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewSchema(config Config) (graphql.Schema, error) {
 | 
					func NewSchema(config Config) (graphql.Schema, error) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 打开数据库连接
 | 
						// 打开数据库连接
 | 
				
			||||||
@@ -27,8 +61,10 @@ func NewSchema(config Config) (graphql.Schema, error) {
 | 
				
			|||||||
		log.Fatalln("连接数据库失败", err)
 | 
							log.Fatalln("连接数据库失败", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var user, article, text *graphql.Object
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 用户的可选字段
 | 
						// 用户的可选字段
 | 
				
			||||||
	user := graphql.NewObject(graphql.ObjectConfig{
 | 
						user = graphql.NewObject(graphql.ObjectConfig{
 | 
				
			||||||
		Name:        "User",
 | 
							Name:        "User",
 | 
				
			||||||
		Description: "用户信息",
 | 
							Description: "用户信息",
 | 
				
			||||||
		Fields: graphql.Fields{
 | 
							Fields: graphql.Fields{
 | 
				
			||||||
@@ -43,7 +79,7 @@ func NewSchema(config Config) (graphql.Schema, error) {
 | 
				
			|||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 文章的可选字段
 | 
						// 文章的可选字段
 | 
				
			||||||
	article := graphql.NewObject(graphql.ObjectConfig{
 | 
						article = graphql.NewObject(graphql.ObjectConfig{
 | 
				
			||||||
		Name:        "Article",
 | 
							Name:        "Article",
 | 
				
			||||||
		Description: "文章信息",
 | 
							Description: "文章信息",
 | 
				
			||||||
		Fields: graphql.Fields{
 | 
							Fields: graphql.Fields{
 | 
				
			||||||
@@ -57,7 +93,7 @@ func NewSchema(config Config) (graphql.Schema, error) {
 | 
				
			|||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 图像中的文字提取
 | 
						// 图像中的文字提取
 | 
				
			||||||
	text := graphql.NewObject(graphql.ObjectConfig{
 | 
						text = graphql.NewObject(graphql.ObjectConfig{
 | 
				
			||||||
		Name:        "Text",
 | 
							Name:        "Text",
 | 
				
			||||||
		Description: "图像中的文字提取",
 | 
							Description: "图像中的文字提取",
 | 
				
			||||||
		Fields: graphql.Fields{
 | 
							Fields: graphql.Fields{
 | 
				
			||||||
@@ -80,18 +116,41 @@ func NewSchema(config Config) (graphql.Schema, error) {
 | 
				
			|||||||
			"description":             &graphql.Field{Type: graphql.String, Description: "图像描述"},
 | 
								"description":             &graphql.Field{Type: graphql.String, Description: "图像描述"},
 | 
				
			||||||
			"tags":                    &graphql.Field{Type: graphql.String, Description: "图像标签"},
 | 
								"tags":                    &graphql.Field{Type: graphql.String, Description: "图像标签"},
 | 
				
			||||||
			"rank":                    &graphql.Field{Type: graphql.String, Description: "图像等级"},
 | 
								"rank":                    &graphql.Field{Type: graphql.String, Description: "图像等级"},
 | 
				
			||||||
			"text":                    &graphql.Field{Type: graphql.NewList(text), Description: "图像中的文字"},
 | 
					 | 
				
			||||||
			"comment_num":             &graphql.Field{Type: graphql.Int, Description: "评论数"},
 | 
								"comment_num":             &graphql.Field{Type: graphql.Int, Description: "评论数"},
 | 
				
			||||||
			"article_category_top_id": &graphql.Field{Type: graphql.Int, Description: "文章分类顶级ID"},
 | 
								"article_category_top_id": &graphql.Field{Type: graphql.Int, Description: "文章分类顶级ID"},
 | 
				
			||||||
			"praise_count":            &graphql.Field{Type: graphql.Int, Description: "点赞数"},
 | 
								"praise_count":            &graphql.Field{Type: graphql.Int, Description: "点赞数"},
 | 
				
			||||||
			"collect_count":           &graphql.Field{Type: graphql.Int, Description: "收藏数"},
 | 
								"collect_count":           &graphql.Field{Type: graphql.Int, Description: "收藏数"},
 | 
				
			||||||
			"create_time":             &graphql.Field{Type: graphql.DateTime, Description: "图像创建时间"},
 | 
								"create_time":             &graphql.Field{Type: graphql.DateTime, Description: "图像创建时间"},
 | 
				
			||||||
			"update_time":             &graphql.Field{Type: graphql.DateTime, Description: "图像更新时间"},
 | 
								"update_time":             &graphql.Field{Type: graphql.DateTime, Description: "图像更新时间"},
 | 
				
			||||||
			"user":                    &graphql.Field{Type: user, Description: "图像所属用户"},
 | 
					 | 
				
			||||||
			"article":                 &graphql.Field{Type: article, Description: "图像所属文章"},
 | 
								"article":                 &graphql.Field{Type: article, Description: "图像所属文章"},
 | 
				
			||||||
 | 
								"text": &graphql.Field{
 | 
				
			||||||
 | 
									Type:        graphql.NewList(text),
 | 
				
			||||||
 | 
									Description: "图像中的文字",
 | 
				
			||||||
 | 
									Args: graphql.FieldConfigArgument{
 | 
				
			||||||
 | 
										"text": &graphql.ArgumentConfig{Type: graphql.String, Description: "筛选含有指定文字的列"},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									Resolve: func(p graphql.ResolveParams) (interface{}, error) {
 | 
				
			||||||
 | 
										if p.Args["text"] != nil {
 | 
				
			||||||
 | 
											var texts TextList
 | 
				
			||||||
 | 
											for _, text := range p.Source.(Image).Text {
 | 
				
			||||||
 | 
												fmt.Println("san", text.Text)
 | 
				
			||||||
 | 
												if strings.Contains(text.Text, p.Args["text"].(string)) {
 | 
				
			||||||
 | 
													texts = append(texts, text)
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											return texts, nil
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										return p.Source.(Image).Text, nil
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						image.AddFieldConfig("user", &graphql.Field{Type: user, Description: "图像所属用户"})
 | 
				
			||||||
 | 
						image.AddFieldConfig("similars", &graphql.Field{Type: graphql.NewList(image), Description: "相似的图像", Resolve: func(p graphql.ResolveParams) (interface{}, error) {
 | 
				
			||||||
 | 
							return []Image{}, nil
 | 
				
			||||||
 | 
						}})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 将 list 中的字段提取出来用于查询
 | 
						// 将 list 中的字段提取出来用于查询
 | 
				
			||||||
	get_fields := func(requestedFields []ast.Selection) (fields []string) {
 | 
						get_fields := func(requestedFields []ast.Selection) (fields []string) {
 | 
				
			||||||
		for _, field := range requestedFields {
 | 
							for _, field := range requestedFields {
 | 
				
			||||||
@@ -108,6 +167,10 @@ func NewSchema(config Config) (graphql.Schema, error) {
 | 
				
			|||||||
							fields = append(fields, "article_id")
 | 
												fields = append(fields, "article_id")
 | 
				
			||||||
							continue
 | 
												continue
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
 | 
											if fieldAST.Name.Value == "similars" {
 | 
				
			||||||
 | 
												// 跳过自定义字段
 | 
				
			||||||
 | 
												continue
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
						fields = append(fields, fieldAST.Name.Value)
 | 
											fields = append(fields, fieldAST.Name.Value)
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
@@ -154,18 +217,15 @@ func NewSchema(config Config) (graphql.Schema, error) {
 | 
				
			|||||||
				if where_str != "" {
 | 
									if where_str != "" {
 | 
				
			||||||
					where_str = "WHERE " + where_str
 | 
										where_str = "WHERE " + where_str
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					 | 
				
			||||||
				var query strings.Builder
 | 
									var query strings.Builder
 | 
				
			||||||
				var users []User
 | 
									var users []User
 | 
				
			||||||
				var total int
 | 
									var total int
 | 
				
			||||||
 | 
					 | 
				
			||||||
				fields := strings.Join(get_fields(p.Info.FieldASTs[0].SelectionSet.Selections), ",")
 | 
									fields := strings.Join(get_fields(p.Info.FieldASTs[0].SelectionSet.Selections), ",")
 | 
				
			||||||
				query.WriteString(fmt.Sprintf("SELECT %s FROM web_member %s LIMIT %d OFFSET %d", fields, where_str, 10, 0))
 | 
									query.WriteString(fmt.Sprintf("SELECT %s FROM web_member %s LIMIT %d OFFSET %d", fields, where_str, 10, 0))
 | 
				
			||||||
				if err := connection.Select(&users, query.String()); err != nil {
 | 
									if err := connection.Select(&users, query.String()); err != nil {
 | 
				
			||||||
					fmt.Println("获取用户列表失败", err)
 | 
										fmt.Println("获取用户列表失败", err)
 | 
				
			||||||
					return nil, err
 | 
										return nil, err
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					 | 
				
			||||||
				if len(users) > 0 {
 | 
									if len(users) > 0 {
 | 
				
			||||||
					query.Reset()
 | 
										query.Reset()
 | 
				
			||||||
					query.WriteString(fmt.Sprintf("SELECT COUNT(*) FROM web_member %s", where_str))
 | 
										query.WriteString(fmt.Sprintf("SELECT COUNT(*) FROM web_member %s", where_str))
 | 
				
			||||||
@@ -174,7 +234,6 @@ func NewSchema(config Config) (graphql.Schema, error) {
 | 
				
			|||||||
						return nil, err
 | 
											return nil, err
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					 | 
				
			||||||
				return map[string]interface{}{
 | 
									return map[string]interface{}{
 | 
				
			||||||
					"list":  users,
 | 
										"list":  users,
 | 
				
			||||||
					"total": total,
 | 
										"total": total,
 | 
				
			||||||
@@ -308,7 +367,7 @@ func NewSchema(config Config) (graphql.Schema, error) {
 | 
				
			|||||||
							"total": 0,
 | 
												"total": 0,
 | 
				
			||||||
						}, nil
 | 
											}, nil
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					where = append(where, fmt.Sprintf("id IN (%s) LIMIT %d", id_list_str, len(id_list)))
 | 
										where = append(where, fmt.Sprintf("id IN (%s)", id_list_str))
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				where_str := strings.Join(where, " AND ")
 | 
									where_str := strings.Join(where, " AND ")
 | 
				
			||||||
@@ -342,17 +401,11 @@ func NewSchema(config Config) (graphql.Schema, error) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
				var images ImageList
 | 
									var images ImageList
 | 
				
			||||||
				var q = query.String()
 | 
									var q = query.String()
 | 
				
			||||||
				fmt.Println(q)
 | 
					 | 
				
			||||||
				if err := connection.Select(&images, q); err != nil {
 | 
									if err := connection.Select(&images, q); err != nil {
 | 
				
			||||||
					fmt.Println("获取图像列表失败", err)
 | 
										fmt.Println("获取图像列表失败", err)
 | 
				
			||||||
					return nil, err
 | 
										return nil, err
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				// 按照 id_list 的顺序重新排序
 | 
					 | 
				
			||||||
				//if len(id_list) > 0 {
 | 
					 | 
				
			||||||
				//	images.SortByIDList(id_list)
 | 
					 | 
				
			||||||
				//}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				// 获取用户信息(如果图像列表不为空且请求字段中包含user)
 | 
									// 获取用户信息(如果图像列表不为空且请求字段中包含user)
 | 
				
			||||||
				if len(images) > 0 && strings.Contains(fields, "user") {
 | 
									if len(images) > 0 && strings.Contains(fields, "user") {
 | 
				
			||||||
					user_ids_str := images.ToAllUserID().ToString()
 | 
										user_ids_str := images.ToAllUserID().ToString()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -78,25 +78,24 @@ func (images *ImageList) SetArticle(articleList []Article) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Image struct {
 | 
					type Image struct {
 | 
				
			||||||
	ID                   int       `json:"id"                      db:"id"`
 | 
						ID           int       `json:"id"            db:"id"`
 | 
				
			||||||
	Width                int       `json:"width"                   db:"width"`
 | 
						Width        int       `json:"width"         db:"width"`
 | 
				
			||||||
	Height               int       `json:"height"                  db:"height"`
 | 
						Height       int       `json:"height"        db:"height"`
 | 
				
			||||||
	Content              string    `json:"content"                 db:"content"`
 | 
						Content      string    `json:"content"       db:"content"`
 | 
				
			||||||
	Remark               string    `json:"remark"                  db:"remark"`
 | 
						Remark       string    `json:"remark"        db:"remark"`
 | 
				
			||||||
	Description          string    `json:"description"             db:"description"`
 | 
						Description  string    `json:"description"   db:"description"`
 | 
				
			||||||
	Tags                 string    `json:"tags"                    db:"tags"`
 | 
						Tags         string    `json:"tags"          db:"tags"`
 | 
				
			||||||
	Rank                 string    `json:"rank"                    db:"rank"`
 | 
						Rank         string    `json:"rank"          db:"rank"`
 | 
				
			||||||
	CommentNum           int       `json:"comment_num"             db:"comment_num"`
 | 
						CommentNum   int       `json:"comment_num"   db:"comment_num"`
 | 
				
			||||||
	ArticleCategoryTopId int       `json:"article_category_top_id" db:"article_category_top_id"`
 | 
						PraiseCount  int       `json:"praise_count"  db:"praise_count"`
 | 
				
			||||||
	PraiseCount          int       `json:"praise_count"            db:"praise_count"`
 | 
						CollectCount int       `json:"collect_count" db:"collect_count"`
 | 
				
			||||||
	CollectCount         int       `json:"collect_count"           db:"collect_count"`
 | 
						ArticleID    int       `json:"article_id"    db:"article_id"`
 | 
				
			||||||
	ArticleID            int       `json:"article_id"              db:"article_id"`
 | 
						UserID       int       `json:"user_id"       db:"user_id"`
 | 
				
			||||||
	UserID               int       `json:"user_id"                 db:"user_id"`
 | 
						CreateTime   time.Time `json:"create_time"   db:"create_time"`
 | 
				
			||||||
	User                 User      `json:"user"                    db:"-"`
 | 
						UpdateTime   time.Time `json:"update_time"   db:"update_time"`
 | 
				
			||||||
	Article              Article   `json:"article"                 db:"-"`
 | 
						Text         TextList  `json:"text"          db:"text"`
 | 
				
			||||||
	CreateTime           time.Time `json:"create_time"             db:"create_time"`
 | 
						User         User      `json:"user"          db:"-"`
 | 
				
			||||||
	UpdateTime           time.Time `json:"update_time"             db:"update_time"`
 | 
						Article      Article   `json:"article"       db:"-"`
 | 
				
			||||||
	Text                 TextList  `json:"text"                    db:"text"`
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type TextList []struct {
 | 
					type TextList []struct {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user