[Files refactor] Bug fixes (#2849)

* Fix scene sorting
* Fix folder-based gallery path sorting
* Fix gallery path filter
* Fix stash-box performer submission
* Fix identify logging
* Remove govet from linter
This commit is contained in:
WithoutPants
2022-08-24 16:37:20 +10:00
parent 00608c167a
commit f4825fadf4
8 changed files with 159 additions and 91 deletions

View File

@@ -9,7 +9,8 @@ linters:
# Default set of linters from golangci-lint # Default set of linters from golangci-lint
- errcheck - errcheck
- gosimple - gosimple
- govet # removed to fix timeout error
# - govet
- ineffassign - ineffassign
- staticcheck - staticcheck
- typecheck - typecheck

View File

@@ -212,7 +212,7 @@ func (t *SceneIdentifier) modifyScene(ctx context.Context, txnManager txn.Manage
// don't update anything if nothing was set // don't update anything if nothing was set
if updater.IsEmpty() { if updater.IsEmpty() {
logger.Debugf("Nothing to set for %s", s.Path) logger.Debugf("Nothing to set for %s", s.Path())
return nil return nil
} }
@@ -225,7 +225,7 @@ func (t *SceneIdentifier) modifyScene(ctx context.Context, txnManager txn.Manage
if title.Ptr() != nil { if title.Ptr() != nil {
as = fmt.Sprintf(" as %s", title.Value) as = fmt.Sprintf(" as %s", title.Value)
} }
logger.Infof("Successfully identified %s%s using %s", s.Path, as, result.source.Name) logger.Infof("Successfully identified %s%s using %s", s.Path(), as, result.source.Name)
return nil return nil
}); err != nil { }); err != nil {

View File

@@ -777,8 +777,9 @@ func (c Client) SubmitSceneDraft(ctx context.Context, scene *models.Scene, endpo
return nil, err return nil, err
} }
for _, stashID := range stashIDs { for _, stashID := range stashIDs {
if stashID.Endpoint == endpoint { c := stashID
studioDraft.ID = &stashID.StashID if c.Endpoint == endpoint {
studioDraft.ID = &c.StashID
break break
} }
} }
@@ -891,89 +892,83 @@ func (c Client) SubmitSceneDraft(ctx context.Context, scene *models.Scene, endpo
func (c Client) SubmitPerformerDraft(ctx context.Context, performer *models.Performer, endpoint string) (*string, error) { func (c Client) SubmitPerformerDraft(ctx context.Context, performer *models.Performer, endpoint string) (*string, error) {
draft := graphql.PerformerDraftInput{} draft := graphql.PerformerDraftInput{}
var image io.Reader var image io.Reader
if err := txn.WithTxn(ctx, c.txnManager, func(ctx context.Context) error { pqb := c.repository.Performer
pqb := c.repository.Performer img, _ := pqb.GetImage(ctx, performer.ID)
img, _ := pqb.GetImage(ctx, performer.ID) if img != nil {
if img != nil { image = bytes.NewReader(img)
image = bytes.NewReader(img) }
}
if performer.Name.Valid { if performer.Name.Valid {
draft.Name = performer.Name.String draft.Name = performer.Name.String
} }
if performer.Birthdate.Valid { if performer.Birthdate.Valid {
draft.Birthdate = &performer.Birthdate.String draft.Birthdate = &performer.Birthdate.String
} }
if performer.Country.Valid { if performer.Country.Valid {
draft.Country = &performer.Country.String draft.Country = &performer.Country.String
} }
if performer.Ethnicity.Valid { if performer.Ethnicity.Valid {
draft.Ethnicity = &performer.Ethnicity.String draft.Ethnicity = &performer.Ethnicity.String
} }
if performer.EyeColor.Valid { if performer.EyeColor.Valid {
draft.EyeColor = &performer.EyeColor.String draft.EyeColor = &performer.EyeColor.String
} }
if performer.FakeTits.Valid { if performer.FakeTits.Valid {
draft.BreastType = &performer.FakeTits.String draft.BreastType = &performer.FakeTits.String
} }
if performer.Gender.Valid { if performer.Gender.Valid {
draft.Gender = &performer.Gender.String draft.Gender = &performer.Gender.String
} }
if performer.HairColor.Valid { if performer.HairColor.Valid {
draft.HairColor = &performer.HairColor.String draft.HairColor = &performer.HairColor.String
} }
if performer.Height.Valid { if performer.Height.Valid {
draft.Height = &performer.Height.String draft.Height = &performer.Height.String
} }
if performer.Measurements.Valid { if performer.Measurements.Valid {
draft.Measurements = &performer.Measurements.String draft.Measurements = &performer.Measurements.String
} }
if performer.Piercings.Valid { if performer.Piercings.Valid {
draft.Piercings = &performer.Piercings.String draft.Piercings = &performer.Piercings.String
} }
if performer.Tattoos.Valid { if performer.Tattoos.Valid {
draft.Tattoos = &performer.Tattoos.String draft.Tattoos = &performer.Tattoos.String
} }
if performer.Aliases.Valid { if performer.Aliases.Valid {
draft.Aliases = &performer.Aliases.String draft.Aliases = &performer.Aliases.String
} }
var urls []string var urls []string
if len(strings.TrimSpace(performer.Twitter.String)) > 0 { if len(strings.TrimSpace(performer.Twitter.String)) > 0 {
urls = append(urls, "https://twitter.com/"+strings.TrimSpace(performer.Twitter.String)) urls = append(urls, "https://twitter.com/"+strings.TrimSpace(performer.Twitter.String))
} }
if len(strings.TrimSpace(performer.Instagram.String)) > 0 { if len(strings.TrimSpace(performer.Instagram.String)) > 0 {
urls = append(urls, "https://instagram.com/"+strings.TrimSpace(performer.Instagram.String)) urls = append(urls, "https://instagram.com/"+strings.TrimSpace(performer.Instagram.String))
} }
if len(strings.TrimSpace(performer.URL.String)) > 0 { if len(strings.TrimSpace(performer.URL.String)) > 0 {
urls = append(urls, strings.TrimSpace(performer.URL.String)) urls = append(urls, strings.TrimSpace(performer.URL.String))
} }
if len(urls) > 0 { if len(urls) > 0 {
draft.Urls = urls draft.Urls = urls
} }
stashIDs, err := pqb.GetStashIDs(ctx, performer.ID) stashIDs, err := pqb.GetStashIDs(ctx, performer.ID)
if err != nil { if err != nil {
return err
}
var stashID *string
for _, v := range stashIDs {
c := v
if v.Endpoint == endpoint {
stashID = &c.StashID
break
}
}
draft.ID = stashID
return nil
}); err != nil {
return nil, err return nil, err
} }
var stashID *string
for _, v := range stashIDs {
c := v
if v.Endpoint == endpoint {
stashID = &c.StashID
break
}
}
draft.ID = stashID
var id *string var id *string
var ret graphql.SubmitPerformerDraft var ret graphql.SubmitPerformerDraft
err := c.submitDraft(ctx, graphql.SubmitPerformerDraftDocument, draft, image, &ret) err = c.submitDraft(ctx, graphql.SubmitPerformerDraftDocument, draft, image, &ret)
id = ret.SubmitPerformerDraft.ID id = ret.SubmitPerformerDraft.ID
return id, err return id, err

View File

@@ -387,11 +387,9 @@ func stringCriterionHandler(c *models.StringCriterionInput, column string) crite
if modifier := c.Modifier; c.Modifier.IsValid() { if modifier := c.Modifier; c.Modifier.IsValid() {
switch modifier { switch modifier {
case models.CriterionModifierIncludes: case models.CriterionModifierIncludes:
clause, thisArgs := getSearchBinding([]string{column}, c.Value, false) f.whereClauses = append(f.whereClauses, getStringSearchClause([]string{column}, c.Value, false))
f.addWhere(clause, thisArgs...)
case models.CriterionModifierExcludes: case models.CriterionModifierExcludes:
clause, thisArgs := getSearchBinding([]string{column}, c.Value, true) f.whereClauses = append(f.whereClauses, getStringSearchClause([]string{column}, c.Value, true))
f.addWhere(clause, thisArgs...)
case models.CriterionModifierEquals: case models.CriterionModifierEquals:
f.addWhere(column+" LIKE ?", c.Value) f.addWhere(column+" LIKE ?", c.Value)
case models.CriterionModifierNotEquals: case models.CriterionModifierNotEquals:

View File

@@ -6,6 +6,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"path/filepath" "path/filepath"
"regexp"
"time" "time"
"github.com/doug-martin/goqu/v9" "github.com/doug-martin/goqu/v9"
@@ -595,7 +596,7 @@ func (qb *GalleryStore) makeFilter(ctx context.Context, galleryFilter *models.Ga
} }
})) }))
query.handleCriterion(ctx, pathCriterionHandler(galleryFilter.Path, "folders.path", "files.basename", qb.addFoldersTable)) query.handleCriterion(ctx, qb.galleryPathCriterionHandler(galleryFilter.Path))
query.handleCriterion(ctx, galleryFileCountCriterionHandler(qb, galleryFilter.FileCount)) query.handleCriterion(ctx, galleryFileCountCriterionHandler(qb, galleryFilter.FileCount))
query.handleCriterion(ctx, intCriterionHandler(galleryFilter.Rating, "galleries.rating", nil)) query.handleCriterion(ctx, intCriterionHandler(galleryFilter.Rating, "galleries.rating", nil))
query.handleCriterion(ctx, stringCriterionHandler(galleryFilter.URL, "galleries.url")) query.handleCriterion(ctx, stringCriterionHandler(galleryFilter.URL, "galleries.url"))
@@ -716,6 +717,71 @@ func (qb *GalleryStore) QueryCount(ctx context.Context, galleryFilter *models.Ga
return query.executeCount(ctx) return query.executeCount(ctx)
} }
func (qb *GalleryStore) galleryPathCriterionHandler(c *models.StringCriterionInput) criterionHandlerFunc {
return func(ctx context.Context, f *filterBuilder) {
if c != nil {
qb.addFoldersTable(f)
f.addLeftJoin(folderTable, "gallery_folder", "galleries.folder_id = gallery_folder.id")
const pathColumn = "folders.path"
const basenameColumn = "files.basename"
const folderPathColumn = "gallery_folder.path"
addWildcards := true
not := false
if modifier := c.Modifier; c.Modifier.IsValid() {
switch modifier {
case models.CriterionModifierIncludes:
clause := getPathSearchClause(pathColumn, basenameColumn, c.Value, addWildcards, not)
clause2 := getStringSearchClause([]string{folderPathColumn}, c.Value, false)
f.whereClauses = append(f.whereClauses, orClauses(clause, clause2))
case models.CriterionModifierExcludes:
not = true
clause := getPathSearchClause(pathColumn, basenameColumn, c.Value, addWildcards, not)
clause2 := getStringSearchClause([]string{folderPathColumn}, c.Value, true)
f.whereClauses = append(f.whereClauses, orClauses(clause, clause2))
case models.CriterionModifierEquals:
addWildcards = false
clause := getPathSearchClause(pathColumn, basenameColumn, c.Value, addWildcards, not)
clause2 := makeClause(folderPathColumn+" LIKE ?", c.Value)
f.whereClauses = append(f.whereClauses, orClauses(clause, clause2))
case models.CriterionModifierNotEquals:
addWildcards = false
not = true
clause := getPathSearchClause(pathColumn, basenameColumn, c.Value, addWildcards, not)
clause2 := makeClause(folderPathColumn+" NOT LIKE ?", c.Value)
f.whereClauses = append(f.whereClauses, orClauses(clause, clause2))
case models.CriterionModifierMatchesRegex:
if _, err := regexp.Compile(c.Value); err != nil {
f.setError(err)
return
}
clause := makeClause(fmt.Sprintf("(%s IS NOT NULL AND %[1]s regexp ?) OR (%s IS NOT NULL AND %[2]s regexp ?)", pathColumn, basenameColumn), c.Value, c.Value)
clause2 := makeClause(fmt.Sprintf("(%s IS NOT NULL AND %[1]s regexp ?)", folderPathColumn), c.Value)
f.whereClauses = append(f.whereClauses, orClauses(clause, clause2))
case models.CriterionModifierNotMatchesRegex:
if _, err := regexp.Compile(c.Value); err != nil {
f.setError(err)
return
}
f.addWhere(fmt.Sprintf("(%s IS NULL OR %[1]s NOT regexp ?) AND (%s IS NULL OR %[2]s NOT regexp ?)", pathColumn, basenameColumn), c.Value, c.Value)
f.addWhere(fmt.Sprintf("(%s IS NULL OR %[1]s NOT regexp ?)", folderPathColumn), c.Value)
case models.CriterionModifierIsNull:
f.whereClauses = append(f.whereClauses, makeClause(fmt.Sprintf("(%s IS NULL OR TRIM(%[1]s) = '' OR %s IS NULL OR TRIM(%[2]s) = '')", pathColumn, basenameColumn)))
f.whereClauses = append(f.whereClauses, makeClause(fmt.Sprintf("(%s IS NULL OR TRIM(%[1]s) = '')", folderPathColumn)))
case models.CriterionModifierNotNull:
clause := makeClause(fmt.Sprintf("(%s IS NOT NULL AND TRIM(%[1]s) != '' AND %s IS NOT NULL AND TRIM(%[2]s) != '')", pathColumn, basenameColumn))
clause2 := makeClause(fmt.Sprintf("(%s IS NOT NULL AND TRIM(%[1]s) != '')", folderPathColumn))
f.whereClauses = append(f.whereClauses, orClauses(clause, clause2))
default:
panic("unsupported string filter modifier")
}
}
}
}
}
func galleryFileCountCriterionHandler(qb *GalleryStore, fileCount *models.IntCriterionInput) criterionHandlerFunc { func galleryFileCountCriterionHandler(qb *GalleryStore, fileCount *models.IntCriterionInput) criterionHandlerFunc {
h := countCriterionHandlerBuilder{ h := countCriterionHandlerBuilder{
primaryTable: galleryTable, primaryTable: galleryTable,
@@ -962,10 +1028,15 @@ func (qb *GalleryStore) setGallerySort(query *queryBuilder, findFilter *models.F
query.addJoins( query.addJoins(
join{ join{
table: folderTable, table: folderTable,
onClause: "files.parent_folder_id = folders.id", onClause: "folders.id = galleries.folder_id",
},
join{
table: folderTable,
as: "file_folder",
onClause: "files.parent_folder_id = file_folder.id",
}, },
) )
query.sortAndPagination += fmt.Sprintf(" ORDER BY folders.path %s, files.basename %[1]s", direction) query.sortAndPagination += fmt.Sprintf(" ORDER BY folders.path %s, file_folder.path %[1]s, files.basename %[1]s", direction)
case "file_mod_time": case "file_mod_time":
sort = "mod_time" sort = "mod_time"
addFileTable() addFileTable()

View File

@@ -1325,12 +1325,15 @@ func (qb *SceneStore) setSceneSort(query *queryBuilder, findFilter *models.FindF
sort = "frame_rate" sort = "frame_rate"
addVideoFileTable() addVideoFileTable()
query.sortAndPagination += getSort(sort, direction, videoFileTable) query.sortAndPagination += getSort(sort, direction, videoFileTable)
case "size": case "filesize":
addFileTable() addFileTable()
query.sortAndPagination += getSort(sort, direction, fileTable) query.sortAndPagination += getSort(sort, direction, fileTable)
case "duration": case "duration":
addVideoFileTable() addVideoFileTable()
query.sortAndPagination += getSort(sort, direction, videoFileTable) query.sortAndPagination += getSort(sort, direction, videoFileTable)
case "interactive", "interactive_speed":
addVideoFileTable()
query.sortAndPagination += getSort(sort, direction, videoFileTable)
default: default:
query.sortAndPagination += getSort(sort, direction, "scenes") query.sortAndPagination += getSort(sort, direction, "scenes")
} }

View File

@@ -3477,7 +3477,7 @@ func TestSceneQuerySorting(t *testing.T) {
}, },
{ {
"file size", "file size",
"size", "filesize",
models.SortDirectionEnumDesc, models.SortDirectionEnumDesc,
-1, -1,
-1, -1,

View File

@@ -105,7 +105,7 @@ func getCountSort(primaryTable, joinTable, primaryFK, direction string) string {
return fmt.Sprintf(" ORDER BY (SELECT COUNT(*) FROM %s WHERE %s = %s.id) %s", joinTable, primaryFK, primaryTable, getSortDirection(direction)) return fmt.Sprintf(" ORDER BY (SELECT COUNT(*) FROM %s WHERE %s = %s.id) %s", joinTable, primaryFK, primaryTable, getSortDirection(direction))
} }
func getSearchBinding(columns []string, q string, not bool) (string, []interface{}) { func getStringSearchClause(columns []string, q string, not bool) sqlClause {
var likeClauses []string var likeClauses []string
var args []interface{} var args []interface{}
@@ -137,7 +137,7 @@ func getSearchBinding(columns []string, q string, not bool) (string, []interface
} }
likes := strings.Join(likeClauses, binaryType) likes := strings.Join(likeClauses, binaryType)
return "(" + likes + ")", args return makeClause("("+likes+")", args...)
} }
func getInBinding(length int) string { func getInBinding(length int) string {