mirror of https://github.com/stashapp/stash.git
[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:
parent
00608c167a
commit
f4825fadf4
|
@ -9,7 +9,8 @@ linters:
|
|||
# Default set of linters from golangci-lint
|
||||
- errcheck
|
||||
- gosimple
|
||||
- govet
|
||||
# removed to fix timeout error
|
||||
# - govet
|
||||
- ineffassign
|
||||
- staticcheck
|
||||
- typecheck
|
||||
|
|
|
@ -212,7 +212,7 @@ func (t *SceneIdentifier) modifyScene(ctx context.Context, txnManager txn.Manage
|
|||
|
||||
// don't update anything if nothing was set
|
||||
if updater.IsEmpty() {
|
||||
logger.Debugf("Nothing to set for %s", s.Path)
|
||||
logger.Debugf("Nothing to set for %s", s.Path())
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -225,7 +225,7 @@ func (t *SceneIdentifier) modifyScene(ctx context.Context, txnManager txn.Manage
|
|||
if title.Ptr() != nil {
|
||||
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
|
||||
}); err != nil {
|
||||
|
|
|
@ -777,8 +777,9 @@ func (c Client) SubmitSceneDraft(ctx context.Context, scene *models.Scene, endpo
|
|||
return nil, err
|
||||
}
|
||||
for _, stashID := range stashIDs {
|
||||
if stashID.Endpoint == endpoint {
|
||||
studioDraft.ID = &stashID.StashID
|
||||
c := stashID
|
||||
if c.Endpoint == endpoint {
|
||||
studioDraft.ID = &c.StashID
|
||||
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) {
|
||||
draft := graphql.PerformerDraftInput{}
|
||||
var image io.Reader
|
||||
if err := txn.WithTxn(ctx, c.txnManager, func(ctx context.Context) error {
|
||||
pqb := c.repository.Performer
|
||||
img, _ := pqb.GetImage(ctx, performer.ID)
|
||||
if img != nil {
|
||||
image = bytes.NewReader(img)
|
||||
}
|
||||
pqb := c.repository.Performer
|
||||
img, _ := pqb.GetImage(ctx, performer.ID)
|
||||
if img != nil {
|
||||
image = bytes.NewReader(img)
|
||||
}
|
||||
|
||||
if performer.Name.Valid {
|
||||
draft.Name = performer.Name.String
|
||||
}
|
||||
if performer.Birthdate.Valid {
|
||||
draft.Birthdate = &performer.Birthdate.String
|
||||
}
|
||||
if performer.Country.Valid {
|
||||
draft.Country = &performer.Country.String
|
||||
}
|
||||
if performer.Ethnicity.Valid {
|
||||
draft.Ethnicity = &performer.Ethnicity.String
|
||||
}
|
||||
if performer.EyeColor.Valid {
|
||||
draft.EyeColor = &performer.EyeColor.String
|
||||
}
|
||||
if performer.FakeTits.Valid {
|
||||
draft.BreastType = &performer.FakeTits.String
|
||||
}
|
||||
if performer.Gender.Valid {
|
||||
draft.Gender = &performer.Gender.String
|
||||
}
|
||||
if performer.HairColor.Valid {
|
||||
draft.HairColor = &performer.HairColor.String
|
||||
}
|
||||
if performer.Height.Valid {
|
||||
draft.Height = &performer.Height.String
|
||||
}
|
||||
if performer.Measurements.Valid {
|
||||
draft.Measurements = &performer.Measurements.String
|
||||
}
|
||||
if performer.Piercings.Valid {
|
||||
draft.Piercings = &performer.Piercings.String
|
||||
}
|
||||
if performer.Tattoos.Valid {
|
||||
draft.Tattoos = &performer.Tattoos.String
|
||||
}
|
||||
if performer.Aliases.Valid {
|
||||
draft.Aliases = &performer.Aliases.String
|
||||
}
|
||||
if performer.Name.Valid {
|
||||
draft.Name = performer.Name.String
|
||||
}
|
||||
if performer.Birthdate.Valid {
|
||||
draft.Birthdate = &performer.Birthdate.String
|
||||
}
|
||||
if performer.Country.Valid {
|
||||
draft.Country = &performer.Country.String
|
||||
}
|
||||
if performer.Ethnicity.Valid {
|
||||
draft.Ethnicity = &performer.Ethnicity.String
|
||||
}
|
||||
if performer.EyeColor.Valid {
|
||||
draft.EyeColor = &performer.EyeColor.String
|
||||
}
|
||||
if performer.FakeTits.Valid {
|
||||
draft.BreastType = &performer.FakeTits.String
|
||||
}
|
||||
if performer.Gender.Valid {
|
||||
draft.Gender = &performer.Gender.String
|
||||
}
|
||||
if performer.HairColor.Valid {
|
||||
draft.HairColor = &performer.HairColor.String
|
||||
}
|
||||
if performer.Height.Valid {
|
||||
draft.Height = &performer.Height.String
|
||||
}
|
||||
if performer.Measurements.Valid {
|
||||
draft.Measurements = &performer.Measurements.String
|
||||
}
|
||||
if performer.Piercings.Valid {
|
||||
draft.Piercings = &performer.Piercings.String
|
||||
}
|
||||
if performer.Tattoos.Valid {
|
||||
draft.Tattoos = &performer.Tattoos.String
|
||||
}
|
||||
if performer.Aliases.Valid {
|
||||
draft.Aliases = &performer.Aliases.String
|
||||
}
|
||||
|
||||
var urls []string
|
||||
if len(strings.TrimSpace(performer.Twitter.String)) > 0 {
|
||||
urls = append(urls, "https://twitter.com/"+strings.TrimSpace(performer.Twitter.String))
|
||||
}
|
||||
if len(strings.TrimSpace(performer.Instagram.String)) > 0 {
|
||||
urls = append(urls, "https://instagram.com/"+strings.TrimSpace(performer.Instagram.String))
|
||||
}
|
||||
if len(strings.TrimSpace(performer.URL.String)) > 0 {
|
||||
urls = append(urls, strings.TrimSpace(performer.URL.String))
|
||||
}
|
||||
if len(urls) > 0 {
|
||||
draft.Urls = urls
|
||||
}
|
||||
var urls []string
|
||||
if len(strings.TrimSpace(performer.Twitter.String)) > 0 {
|
||||
urls = append(urls, "https://twitter.com/"+strings.TrimSpace(performer.Twitter.String))
|
||||
}
|
||||
if len(strings.TrimSpace(performer.Instagram.String)) > 0 {
|
||||
urls = append(urls, "https://instagram.com/"+strings.TrimSpace(performer.Instagram.String))
|
||||
}
|
||||
if len(strings.TrimSpace(performer.URL.String)) > 0 {
|
||||
urls = append(urls, strings.TrimSpace(performer.URL.String))
|
||||
}
|
||||
if len(urls) > 0 {
|
||||
draft.Urls = urls
|
||||
}
|
||||
|
||||
stashIDs, err := pqb.GetStashIDs(ctx, performer.ID)
|
||||
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 {
|
||||
stashIDs, err := pqb.GetStashIDs(ctx, performer.ID)
|
||||
if err != nil {
|
||||
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 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
|
||||
|
||||
return id, err
|
||||
|
|
|
@ -387,11 +387,9 @@ func stringCriterionHandler(c *models.StringCriterionInput, column string) crite
|
|||
if modifier := c.Modifier; c.Modifier.IsValid() {
|
||||
switch modifier {
|
||||
case models.CriterionModifierIncludes:
|
||||
clause, thisArgs := getSearchBinding([]string{column}, c.Value, false)
|
||||
f.addWhere(clause, thisArgs...)
|
||||
f.whereClauses = append(f.whereClauses, getStringSearchClause([]string{column}, c.Value, false))
|
||||
case models.CriterionModifierExcludes:
|
||||
clause, thisArgs := getSearchBinding([]string{column}, c.Value, true)
|
||||
f.addWhere(clause, thisArgs...)
|
||||
f.whereClauses = append(f.whereClauses, getStringSearchClause([]string{column}, c.Value, true))
|
||||
case models.CriterionModifierEquals:
|
||||
f.addWhere(column+" LIKE ?", c.Value)
|
||||
case models.CriterionModifierNotEquals:
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
"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, intCriterionHandler(galleryFilter.Rating, "galleries.rating", nil))
|
||||
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)
|
||||
}
|
||||
|
||||
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 {
|
||||
h := countCriterionHandlerBuilder{
|
||||
primaryTable: galleryTable,
|
||||
|
@ -962,10 +1028,15 @@ func (qb *GalleryStore) setGallerySort(query *queryBuilder, findFilter *models.F
|
|||
query.addJoins(
|
||||
join{
|
||||
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":
|
||||
sort = "mod_time"
|
||||
addFileTable()
|
||||
|
|
|
@ -1325,12 +1325,15 @@ func (qb *SceneStore) setSceneSort(query *queryBuilder, findFilter *models.FindF
|
|||
sort = "frame_rate"
|
||||
addVideoFileTable()
|
||||
query.sortAndPagination += getSort(sort, direction, videoFileTable)
|
||||
case "size":
|
||||
case "filesize":
|
||||
addFileTable()
|
||||
query.sortAndPagination += getSort(sort, direction, fileTable)
|
||||
case "duration":
|
||||
addVideoFileTable()
|
||||
query.sortAndPagination += getSort(sort, direction, videoFileTable)
|
||||
case "interactive", "interactive_speed":
|
||||
addVideoFileTable()
|
||||
query.sortAndPagination += getSort(sort, direction, videoFileTable)
|
||||
default:
|
||||
query.sortAndPagination += getSort(sort, direction, "scenes")
|
||||
}
|
||||
|
|
|
@ -3477,7 +3477,7 @@ func TestSceneQuerySorting(t *testing.T) {
|
|||
},
|
||||
{
|
||||
"file size",
|
||||
"size",
|
||||
"filesize",
|
||||
models.SortDirectionEnumDesc,
|
||||
-1,
|
||||
-1,
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
||||
func getSearchBinding(columns []string, q string, not bool) (string, []interface{}) {
|
||||
func getStringSearchClause(columns []string, q string, not bool) sqlClause {
|
||||
var likeClauses []string
|
||||
var args []interface{}
|
||||
|
||||
|
@ -137,7 +137,7 @@ func getSearchBinding(columns []string, q string, not bool) (string, []interface
|
|||
}
|
||||
likes := strings.Join(likeClauses, binaryType)
|
||||
|
||||
return "(" + likes + ")", args
|
||||
return makeClause("("+likes+")", args...)
|
||||
}
|
||||
|
||||
func getInBinding(length int) string {
|
||||
|
|
Loading…
Reference in New Issue