Shioriko/pkg/services/tag.go

311 lines
8.0 KiB
Go

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
}