package services import ( "errors" "fmt" "strings" "github.com/Damillora/Shioriko/pkg/database" "github.com/Damillora/Shioriko/pkg/models" "github.com/google/uuid" ) func GetTagAll() []models.TagListItem { var tags []models.TagListItem database.DB.Model(&database.Tag{}). Joins("join tag_types on tag_types.id = tags.tag_type_id"). Joins("left join post_tags on post_tags.tag_id = tags.id"). Select("tags.id as tag_id, tags.name as tag_name, tag_types.name as tag_type, count(post_tags.post_id) as post_count"). Group("tags.id, tags.name, tag_types.name"). Order("post_count DESC"). Find(&tags) return tags } func GetTagFilterString(tagString []string) []models.TagListItem { tagObjs, _ := ParseReadTags(tagString) return GetTagFilter(tagObjs) } func GetTagFilter(tagObjs []database.Tag) []models.TagListItem { var tagIds []string for _, val := range tagObjs { tagIds = append(tagIds, val.ID) } var tags []models.TagListItem database.DB.Model(&tagObjs). Joins("join tag_types on tag_types.id = tags.tag_type_id"). Joins("left join post_tags on post_tags.tag_id = tags.id"). Select("tags.id as tag_id, tags.name as tag_name, tag_types.name as tag_type, count(post_tags.post_id) as post_count"). Group("tags.id, tags.name, tag_types.name"). Order("post_count DESC"). Find(&tags, tagIds) return tags } func GetTag(tagString string) (*models.TagReadModel, error) { tagObj, err := FindTag(tagString) if err != nil { return nil, err } var tagModel models.TagReadModel database.DB.Model(&tagObj). Joins("join tag_types on tag_types.id = tags.tag_type_id"). Joins("left join post_tags on post_tags.tag_id = tags.id"). Select("tags.id as tag_id, tags.name as tag_name, tag_types.name as tag_type, tags.note as tag_note, count(post_tags.post_id) as post_count"). Group("tags.id, tags.name, tag_types.name, tags.note"). First(&tagModel, "tags.id = ? ", tagObj.ID) return &tagModel, nil } func GetTagAutocomplete(searchValue string, forcePositive bool) []string { if forcePositive { return getPositiveTagAutocomplete(strings.TrimPrefix(searchValue, "-")) } if strings.HasPrefix(searchValue, "-") { return getNegativeTagAutocomplete(strings.TrimPrefix(searchValue, "-")) } else { return getPositiveTagAutocomplete(searchValue) } } func getPositiveTagAutocomplete(searchValue string) []string { var tags []string query := database.DB.Model(&database.Tag{}). Joins("join tag_types on tag_types.id = tags.tag_type_id"). Select("concat(tag_types.name,':',tags.name) as name") tagFields := strings.Split(searchValue, ":") if len(tagFields) == 2 { query = query. Where("tags.name LIKE ?", "%"+tagFields[1]+"%"). Where("tag_types.name = ?", tagFields[0]) } else if len(tagFields) == 1 { query = query. Where("tags.name LIKE ?", "%"+tagFields[0]+"%") } result := query.Find(&tags) if result.Error != nil { return []string{} } return tags } func getNegativeTagAutocomplete(searchValue string) []string { var tags []string query := database.DB.Model(&database.Tag{}). Joins("join tag_types on tag_types.id = tags.tag_type_id"). Select("concat('-',tag_types.name,':',tags.name) as name") tagFields := strings.Split(searchValue, ":") if len(tagFields) == 2 { query = query. Where("tags.name LIKE ?", "%"+tagFields[1]+"%"). Where("tag_types.name = ?", tagFields[0]) } else if len(tagFields) == 1 { query = query. Where("tags.name LIKE ?", "%"+tagFields[0]+"%") } result := query.Find(&tags) if result.Error != nil { return []string{} } return tags } func FindTagGeneric(tagName string) (*database.Tag, error) { var tag database.Tag result := database.DB.Where("name = ?", tagName).First(&tag) if result.Error != nil { return nil, result.Error } return &tag, nil } func FindTagComplex(tagName string, tagTypeString string) (*database.Tag, error) { var tag database.Tag var tagType database.TagType result := database.DB.Where("name = ?", tagTypeString).First(&tagType) if result.Error != nil { return nil, result.Error } result = database.DB.Where("name = ? AND tag_type_id = ? ", tagName, tagType.ID).First(&tag) if result.Error != nil { return nil, result.Error } return &tag, nil } func CreateOrUpdateTagGeneric(tagName string) (*database.Tag, error) { tag, err := FindTagGeneric(tagName) if err != nil { var tagType database.TagType database.DB.Where("name = ?", "general").First(&tagType) tag = &database.Tag{ ID: uuid.NewString(), Name: tagName, TagTypeID: tagType.ID, } result := database.DB.Create(&tag) if result.Error != nil { return nil, result.Error } } return tag, nil } func CreateOrUpdateTagComplex(tagName string, tagTypeString string) (*database.Tag, error) { tag, err := FindTagComplex(tagName, tagTypeString) if err != nil { var tagType database.TagType result := database.DB.Where("name = ?", tagTypeString).First(&tagType) if result.Error != nil { return nil, result.Error } tag = &database.Tag{ ID: uuid.NewString(), Name: tagName, TagTypeID: tagType.ID, } result = database.DB.Create(&tag) if result.Error != nil { return nil, result.Error } } return tag, nil } func CreateOrUpdateTag(tagSyntax string) (*database.Tag, error) { tagFields := strings.Split(tagSyntax, ":") var tagName string var tagType string if len(tagFields) == 1 { tagName = tagFields[0] return CreateOrUpdateTagGeneric(tagName) } else if len(tagFields) == 2 { tagType = tagFields[0] tagName = tagFields[1] return CreateOrUpdateTagComplex(tagName, tagType) } else { return nil, errors.New("Malformed tag syntax") } } func FindTag(tagSyntax string) (*database.Tag, error) { tagFields := strings.Split(tagSyntax, ":") var tagName string var tagType string if len(tagFields) == 1 { tagName = tagFields[0] return FindTagGeneric(tagName) } else if len(tagFields) == 2 { tagType = tagFields[0] tagName = tagFields[1] return FindTagComplex(tagName, tagType) } else { return nil, errors.New("Malformed tag syntax") } } func ParseTags(tags []string) ([]database.Tag, error) { var result []database.Tag for _, tagSyntax := range tags { tag, err := CreateOrUpdateTag(tagSyntax) if err != nil { return nil, err } result = append(result, *tag) } return result, nil } func ParseReadTags(tags []string) ([]database.Tag, error) { var result []database.Tag for _, tagSyntax := range tags { tag, err := FindTag(tagSyntax) if err != nil { return nil, err } result = append(result, *tag) } return result, nil } func UpdateTagNotes(tagString string, notes string) error { tagObj, err := FindTag(tagString) if err != nil { return err } tagObj.Note = notes result := database.DB.Save(&tagObj) if result.Error != nil { return result.Error } return nil } func UpdateTag(tagString string, model models.TagUpdateModel) error { tagObj, err := FindTag(tagString) if err != nil { return err } tagObj.TagTypeID = model.TagTypeID tagObj.Name = model.Name result := database.DB.Save(&tagObj) if result.Error != nil { return result.Error } return nil } func GetRelatedTags(tagSyntax string) ([]models.TagListItem, error) { tags, err := FindTag(tagSyntax) if err != nil { return nil, err } var postIds []string database.DB. Model(&tags). Joins("join post_tags on post_tags.tag_id = tags.id"). Select("post_tags.post_id"). Where("post_tags.tag_id = ?", tags.ID). Find(&postIds) var tagIds []string database.DB. Model(&tags). Joins("join post_tags on post_tags.tag_id = tags.id"). Select("post_tags.tag_id"). Where("post_tags.post_id IN ?", postIds). Find(&tagIds) fmt.Printf("%+v", tags) fmt.Println() fmt.Printf("%v", tagIds) fmt.Println() var tagInfo []models.TagListItem database.DB.Model(&tags). Joins("join tag_types on tag_types.id = tags.tag_type_id"). Joins("left join post_tags on post_tags.tag_id = tags.id"). Select("tags.id as tag_id, tags.name as tag_name, tag_types.name as tag_type, count(post_tags.post_id) as post_count"). Group("tags.id, tags.name, tag_types.name"). Order("post_count DESC"). Find(&tagInfo, tagIds) return tagInfo, nil }