mirror of
https://github.com/wgh136/nysoure.git
synced 2025-09-27 04:17:23 +00:00
Add tag type and tag alias.
This commit is contained in:
@@ -36,7 +36,9 @@ func handleSearchTag(c fiber.Ctx) error {
|
||||
return model.NewRequestError("Keyword is required")
|
||||
}
|
||||
keyword = strings.TrimSpace(keyword)
|
||||
tags, err := service.SearchTag(keyword)
|
||||
mainTagStr := c.Query("main_tag")
|
||||
mainTag := mainTagStr == "true" || mainTagStr == "1"
|
||||
tags, err := service.SearchTag(keyword, mainTag)
|
||||
if tags == nil {
|
||||
tags = []model.TagView{}
|
||||
}
|
||||
@@ -66,7 +68,7 @@ func handleDeleteTag(c fiber.Ctx) error {
|
||||
})
|
||||
}
|
||||
|
||||
func handleSetTagDescription(c fiber.Ctx) error {
|
||||
func handleSetTagInfo(c fiber.Ctx) error {
|
||||
uid, ok := c.Locals("uid").(uint)
|
||||
if !ok {
|
||||
return model.NewUnAuthorizedError("You must be logged in to set tag description")
|
||||
@@ -76,11 +78,19 @@ func handleSetTagDescription(c fiber.Ctx) error {
|
||||
return model.NewRequestError("Invalid tag ID")
|
||||
}
|
||||
description := c.FormValue("description")
|
||||
if description == "" {
|
||||
return model.NewRequestError("Description is required")
|
||||
}
|
||||
description = strings.TrimSpace(description)
|
||||
t, err := service.SetTagDescription(uid, uint(id), description)
|
||||
aliasOfStr := c.FormValue("alias_of")
|
||||
var aliasOf *uint
|
||||
if aliasOfStr != "" {
|
||||
aliasID, err := strconv.Atoi(aliasOfStr)
|
||||
if err != nil {
|
||||
return model.NewRequestError("Invalid alias ID")
|
||||
}
|
||||
aliasUint := uint(aliasID)
|
||||
aliasOf = &aliasUint
|
||||
}
|
||||
tagType := c.FormValue("type")
|
||||
t, err := service.SetTagInfo(uid, uint(id), description, aliasOf, tagType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -118,7 +128,7 @@ func AddTagRoutes(api fiber.Router) {
|
||||
tag.Post("/", handleCreateTag)
|
||||
tag.Get("/search", handleSearchTag)
|
||||
tag.Delete("/:id", handleDeleteTag)
|
||||
tag.Put("/:id/description", handleSetTagDescription)
|
||||
tag.Put("/:id/info", handleSetTagInfo)
|
||||
tag.Get("/:name", handleGetTagByName)
|
||||
}
|
||||
}
|
||||
|
@@ -180,20 +180,37 @@ func searchWithKeyword(keyword string) ([]model.Resource, error) {
|
||||
}
|
||||
if len([]rune(keyword)) < 20 {
|
||||
var tag model.Tag
|
||||
if err := db.Where("name = ?", keyword).First(&tag).Error; err != nil {
|
||||
var err error
|
||||
if tag, err = GetTagByName(keyword); err != nil {
|
||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
if err := db.Model(&tag).Preload("Resources").Find(&tag).Error; err != nil {
|
||||
if tag.AliasOf != nil {
|
||||
tag, err = GetTagByID(*tag.AliasOf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
var tagIds []uint
|
||||
tagIds = append(tagIds, tag.ID)
|
||||
for _, alias := range tag.Aliases {
|
||||
tagIds = append(tagIds, alias.ID)
|
||||
}
|
||||
var resources []model.Resource
|
||||
subQuery := db.Table("resource_tags").
|
||||
Select("resource_id").
|
||||
Where("tag_id IN ?", tagIds).
|
||||
Group("resource_id")
|
||||
if err := db.Where("id IN (?)", subQuery).Select("id", "title", "alternative_titles").Preload("Tags").Find(&resources).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return tag.Resources, nil
|
||||
return resources, nil
|
||||
}
|
||||
}
|
||||
if len([]rune(keyword)) < 80 {
|
||||
var resources []model.Resource
|
||||
if err := db.Where("title LIKE ?", "%"+keyword+"%").Or("alternative_titles LIKE ?", "%"+keyword+"%").Find(&resources).Error; err != nil {
|
||||
if err := db.Where("title LIKE ?", "%"+keyword+"%").Or("alternative_titles LIKE ?", "%"+keyword+"%").Select("id", "title", "alternative_titles").Preload("Tags").Find(&resources).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resources, nil
|
||||
@@ -202,23 +219,53 @@ func searchWithKeyword(keyword string) ([]model.Resource, error) {
|
||||
}
|
||||
|
||||
func GetResourceByTag(tagID uint, page int, pageSize int) ([]model.Resource, int, error) {
|
||||
var tag model.Tag
|
||||
|
||||
total := db.Model(&model.Tag{
|
||||
Model: gorm.Model{
|
||||
ID: tagID,
|
||||
},
|
||||
}).Association("Resources").Count()
|
||||
|
||||
if err := db.Model(&model.Tag{}).Where("id = ?", tagID).Preload("Resources", func(tx *gorm.DB) *gorm.DB {
|
||||
return tx.Offset((page - 1) * pageSize).Limit(pageSize).Preload("Tags").Preload("User").Preload("Images").Order("created_at DESC")
|
||||
}).First(&tag).Error; err != nil {
|
||||
tag, err := GetTagByID(tagID)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
totalPages := (int(total) + pageSize - 1) / pageSize
|
||||
if tag.AliasOf != nil {
|
||||
tag, err = GetTagByID(*tag.AliasOf)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
}
|
||||
|
||||
return tag.Resources, totalPages, nil
|
||||
var tagIds []uint
|
||||
tagIds = append(tagIds, tag.ID)
|
||||
for _, alias := range tag.Aliases {
|
||||
tagIds = append(tagIds, alias.ID)
|
||||
}
|
||||
|
||||
var resources []model.Resource
|
||||
var total int64
|
||||
|
||||
subQuery := db.Table("resource_tags").
|
||||
Select("resource_id").
|
||||
Where("tag_id IN ?", tagIds).
|
||||
Group("resource_id")
|
||||
|
||||
if err := db.Model(&model.Resource{}).
|
||||
Where("id IN (?)", subQuery).
|
||||
Count(&total).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
if err := db.Where("id IN (?)", subQuery).
|
||||
Offset((page - 1) * pageSize).
|
||||
Limit(pageSize).
|
||||
Preload("User").
|
||||
Preload("Images").
|
||||
Preload("Tags").
|
||||
Preload("Files").
|
||||
Order("created_at DESC").
|
||||
Find(&resources).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
totalPages := (total + int64(pageSize) - 1) / int64(pageSize)
|
||||
|
||||
return resources, int(totalPages), nil
|
||||
}
|
||||
|
||||
func ExistsResource(id uint) (bool, error) {
|
||||
|
@@ -16,10 +16,14 @@ func CreateTag(tag string) (model.Tag, error) {
|
||||
return t, nil
|
||||
}
|
||||
|
||||
func SearchTag(keyword string) ([]model.Tag, error) {
|
||||
func SearchTag(keyword string, mainTag bool) ([]model.Tag, error) {
|
||||
// Search for a tag by its name in the database
|
||||
var t []model.Tag
|
||||
if err := db.Model(&model.Tag{}).Where("name Like ?", "%"+keyword+"%").Limit(10).Find(&t).Error; err != nil {
|
||||
query := db.Model(&model.Tag{}).Where("name Like ?", "%"+keyword+"%")
|
||||
if mainTag {
|
||||
query = query.Where("alias_of IS NULL")
|
||||
}
|
||||
if err := query.Limit(10).Find(&t).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return t, nil
|
||||
@@ -38,7 +42,7 @@ func DeleteTag(id uint) error {
|
||||
func GetTagByID(id uint) (model.Tag, error) {
|
||||
// Retrieve a tag by its ID from the database
|
||||
var t model.Tag
|
||||
if err := db.First(&t, id).Error; err != nil {
|
||||
if err := db.Preload("Aliases").First(&t, id).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return model.Tag{}, model.NewNotFoundError("Tag not found")
|
||||
}
|
||||
@@ -50,7 +54,7 @@ func GetTagByID(id uint) (model.Tag, error) {
|
||||
func GetTagByName(name string) (model.Tag, error) {
|
||||
// Retrieve a tag by its name from the database
|
||||
var t model.Tag
|
||||
if err := db.Where("name = ?", name).First(&t).Error; err != nil {
|
||||
if err := db.Preload("Aliases").Where("name = ?", name).First(&t).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return model.Tag{}, model.NewNotFoundError("Tag not found")
|
||||
}
|
||||
@@ -59,8 +63,14 @@ func GetTagByName(name string) (model.Tag, error) {
|
||||
return t, nil
|
||||
}
|
||||
|
||||
func SetTagDescription(id uint, description string) error {
|
||||
if err := db.Model(model.Tag{}).Where("id = ?", id).Update("description", description).Error; err != nil {
|
||||
func SetTagInfo(id uint, description string, aliasOf *uint, tagType string) error {
|
||||
t := model.Tag{Model: gorm.Model{
|
||||
ID: id,
|
||||
}, Description: description, Type: tagType, AliasOf: aliasOf}
|
||||
if err := db.Model(&t).Updates(t).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return model.NewNotFoundError("Tag not found")
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
@@ -6,19 +6,30 @@ type Tag struct {
|
||||
gorm.Model
|
||||
Name string `gorm:"unique"`
|
||||
Description string
|
||||
AliasOf *uint `gorm:"default:NULL"` // Foreign key for aliasing, can be NULL
|
||||
Type string
|
||||
Resources []Resource `gorm:"many2many:resource_tags;"`
|
||||
Aliases []Tag `gorm:"foreignKey:AliasOf;references:ID"`
|
||||
}
|
||||
|
||||
type TagView struct {
|
||||
ID uint `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
ID uint `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Type string `json:"type"`
|
||||
Aliases []string `json:"aliases"`
|
||||
}
|
||||
|
||||
func (t *Tag) ToView() *TagView {
|
||||
aliases := make([]string, 0, len(t.Aliases))
|
||||
for _, alias := range t.Aliases {
|
||||
aliases = append(aliases, alias.Name)
|
||||
}
|
||||
return &TagView{
|
||||
ID: t.ID,
|
||||
Name: t.Name,
|
||||
Description: t.Description,
|
||||
Type: t.Type,
|
||||
Aliases: aliases,
|
||||
}
|
||||
}
|
||||
|
@@ -27,6 +27,12 @@ func GetTag(id uint) (*model.TagView, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if t.AliasOf != nil {
|
||||
t, err = dao.GetTagByID(*t.AliasOf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return t.ToView(), nil
|
||||
}
|
||||
|
||||
@@ -35,11 +41,17 @@ func GetTagByName(name string) (*model.TagView, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if t.AliasOf != nil {
|
||||
t, err = dao.GetTagByID(*t.AliasOf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return t.ToView(), nil
|
||||
}
|
||||
|
||||
func SearchTag(name string) ([]model.TagView, error) {
|
||||
tags, err := dao.SearchTag(name)
|
||||
func SearchTag(name string, mainTag bool) ([]model.TagView, error) {
|
||||
tags, err := dao.SearchTag(name, mainTag)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -54,7 +66,7 @@ func DeleteTag(id uint) error {
|
||||
return dao.DeleteTag(id)
|
||||
}
|
||||
|
||||
func SetTagDescription(uid uint, id uint, description string) (*model.TagView, error) {
|
||||
func SetTagInfo(uid uint, id uint, description string, aliasOf *uint, tagType string) (*model.TagView, error) {
|
||||
canUpload, err := checkUserCanUpload(uid)
|
||||
if err != nil {
|
||||
log.Error("Error checking user permissions:", err)
|
||||
@@ -63,13 +75,18 @@ func SetTagDescription(uid uint, id uint, description string) (*model.TagView, e
|
||||
if !canUpload {
|
||||
return nil, model.NewUnAuthorizedError("User cannot set tag description")
|
||||
}
|
||||
if err := dao.SetTagInfo(id, description, aliasOf, tagType); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
t, err := dao.GetTagByID(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
t.Description = description
|
||||
if err := dao.SetTagDescription(id, description); err != nil {
|
||||
return nil, err
|
||||
if t.AliasOf != nil {
|
||||
t, err = dao.GetTagByID(*t.AliasOf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return t.ToView(), nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user