diff --git a/internal/autotag/gallery.go b/internal/autotag/gallery.go index 603e3e36a..3bdfd3c15 100644 --- a/internal/autotag/gallery.go +++ b/internal/autotag/gallery.go @@ -7,12 +7,16 @@ import ( ) func getGalleryFileTagger(s *models.Gallery, cache *match.Cache) tagger { + // only trim the extension if gallery is file-based + trimExt := s.Zip + return tagger{ - ID: s.ID, - Type: "gallery", - Name: s.GetTitle(), - Path: s.Path.String, - cache: cache, + ID: s.ID, + Type: "gallery", + Name: s.GetTitle(), + Path: s.Path.String, + trimExt: trimExt, + cache: cache, } } diff --git a/internal/autotag/scene_test.go b/internal/autotag/scene_test.go index 190b16b8e..578b9e7f6 100644 --- a/internal/autotag/scene_test.go +++ b/internal/autotag/scene_test.go @@ -34,6 +34,7 @@ func generateNamePatterns(name, separator, ext string) []string { ret = append(ret, fmt.Sprintf("aaa%s%s.%s", separator, name, ext)) ret = append(ret, fmt.Sprintf("aaa%s%s%sbbb.%s", separator, name, separator, ext)) ret = append(ret, fmt.Sprintf("dir/%s%saaa.%s", name, separator, ext)) + ret = append(ret, fmt.Sprintf("dir%sdir/%s%saaa.%s", separator, name, separator, ext)) ret = append(ret, fmt.Sprintf("dir\\%s%saaa.%s", name, separator, ext)) ret = append(ret, fmt.Sprintf("%s%saaa/dir/bbb.%s", name, separator, ext)) ret = append(ret, fmt.Sprintf("%s%saaa\\dir\\bbb.%s", name, separator, ext)) diff --git a/internal/autotag/tagger.go b/internal/autotag/tagger.go index 624d29f5a..4ea1fbc01 100644 --- a/internal/autotag/tagger.go +++ b/internal/autotag/tagger.go @@ -22,10 +22,11 @@ import ( ) type tagger struct { - ID int - Type string - Name string - Path string + ID int + Type string + Name string + Path string + trimExt bool cache *match.Cache } @@ -41,7 +42,7 @@ func (t *tagger) addLog(otherType, otherName string) { } func (t *tagger) tagPerformers(performerReader models.PerformerReader, addFunc addLinkFunc) error { - others, err := match.PathToPerformers(t.Path, performerReader, t.cache) + others, err := match.PathToPerformers(t.Path, performerReader, t.cache, t.trimExt) if err != nil { return err } @@ -62,7 +63,7 @@ func (t *tagger) tagPerformers(performerReader models.PerformerReader, addFunc a } func (t *tagger) tagStudios(studioReader models.StudioReader, addFunc addLinkFunc) error { - studio, err := match.PathToStudio(t.Path, studioReader, t.cache) + studio, err := match.PathToStudio(t.Path, studioReader, t.cache, t.trimExt) if err != nil { return err } @@ -83,7 +84,7 @@ func (t *tagger) tagStudios(studioReader models.StudioReader, addFunc addLinkFun } func (t *tagger) tagTags(tagReader models.TagReader, addFunc addLinkFunc) error { - others, err := match.PathToTags(t.Path, tagReader, t.cache) + others, err := match.PathToTags(t.Path, tagReader, t.cache, t.trimExt) if err != nil { return err } diff --git a/pkg/match/path.go b/pkg/match/path.go index 47a7ad26e..4f20423dd 100644 --- a/pkg/match/path.go +++ b/pkg/match/path.go @@ -37,13 +37,15 @@ func getPathQueryRegex(name string) string { return ret } -func getPathWords(path string) []string { +func getPathWords(path string, trimExt bool) []string { retStr := path - // remove the extension - ext := filepath.Ext(retStr) - if ext != "" { - retStr = strings.TrimSuffix(retStr, ext) + if trimExt { + // remove the extension + ext := filepath.Ext(retStr) + if ext != "" { + retStr = strings.TrimSuffix(retStr, ext) + } } // handle path separators @@ -136,8 +138,8 @@ func getPerformers(words []string, performerReader models.PerformerReader, cache return append(performers, swPerformers...), nil } -func PathToPerformers(path string, reader models.PerformerReader, cache *Cache) ([]*models.Performer, error) { - words := getPathWords(path) +func PathToPerformers(path string, reader models.PerformerReader, cache *Cache, trimExt bool) ([]*models.Performer, error) { + words := getPathWords(path, trimExt) performers, err := getPerformers(words, reader, cache) if err != nil { @@ -172,8 +174,8 @@ func getStudios(words []string, reader models.StudioReader, cache *Cache) ([]*mo // PathToStudio returns the Studio that matches the given path. // Where multiple matching studios are found, the one that matches the latest // position in the path is returned. -func PathToStudio(path string, reader models.StudioReader, cache *Cache) (*models.Studio, error) { - words := getPathWords(path) +func PathToStudio(path string, reader models.StudioReader, cache *Cache, trimExt bool) (*models.Studio, error) { + words := getPathWords(path, trimExt) candidates, err := getStudios(words, reader, cache) if err != nil { @@ -220,8 +222,8 @@ func getTags(words []string, reader models.TagReader, cache *Cache) ([]*models.T return append(tags, swTags...), nil } -func PathToTags(path string, reader models.TagReader, cache *Cache) ([]*models.Tag, error) { - words := getPathWords(path) +func PathToTags(path string, reader models.TagReader, cache *Cache, trimExt bool) ([]*models.Tag, error) { + words := getPathWords(path, trimExt) tags, err := getTags(words, reader, cache) if err != nil { diff --git a/pkg/scraper/autotag.go b/pkg/scraper/autotag.go index 20940fce2..4a86d8df2 100644 --- a/pkg/scraper/autotag.go +++ b/pkg/scraper/autotag.go @@ -21,8 +21,8 @@ type autotagScraper struct { globalConfig GlobalConfig } -func autotagMatchPerformers(path string, performerReader models.PerformerReader) ([]*models.ScrapedPerformer, error) { - p, err := match.PathToPerformers(path, performerReader, nil) +func autotagMatchPerformers(path string, performerReader models.PerformerReader, trimExt bool) ([]*models.ScrapedPerformer, error) { + p, err := match.PathToPerformers(path, performerReader, nil, trimExt) if err != nil { return nil, fmt.Errorf("error matching performers: %w", err) } @@ -45,8 +45,8 @@ func autotagMatchPerformers(path string, performerReader models.PerformerReader) return ret, nil } -func autotagMatchStudio(path string, studioReader models.StudioReader) (*models.ScrapedStudio, error) { - studio, err := match.PathToStudio(path, studioReader, nil) +func autotagMatchStudio(path string, studioReader models.StudioReader, trimExt bool) (*models.ScrapedStudio, error) { + studio, err := match.PathToStudio(path, studioReader, nil, trimExt) if err != nil { return nil, fmt.Errorf("error matching studios: %w", err) } @@ -62,8 +62,8 @@ func autotagMatchStudio(path string, studioReader models.StudioReader) (*models. return nil, nil } -func autotagMatchTags(path string, tagReader models.TagReader) ([]*models.ScrapedTag, error) { - t, err := match.PathToTags(path, tagReader, nil) +func autotagMatchTags(path string, tagReader models.TagReader, trimExt bool) ([]*models.ScrapedTag, error) { + t, err := match.PathToTags(path, tagReader, nil, trimExt) if err != nil { return nil, fmt.Errorf("error matching tags: %w", err) } @@ -85,20 +85,21 @@ func autotagMatchTags(path string, tagReader models.TagReader) ([]*models.Scrape func (s autotagScraper) viaScene(ctx context.Context, _client *http.Client, scene *models.Scene) (*models.ScrapedScene, error) { var ret *models.ScrapedScene + const trimExt = false // populate performers, studio and tags based on scene path if err := s.txnManager.WithReadTxn(ctx, func(r models.ReaderRepository) error { path := scene.Path - performers, err := autotagMatchPerformers(path, r.Performer()) + performers, err := autotagMatchPerformers(path, r.Performer(), trimExt) if err != nil { return fmt.Errorf("autotag scraper viaScene: %w", err) } - studio, err := autotagMatchStudio(path, r.Studio()) + studio, err := autotagMatchStudio(path, r.Studio(), trimExt) if err != nil { return fmt.Errorf("autotag scraper viaScene: %w", err) } - tags, err := autotagMatchTags(path, r.Tag()) + tags, err := autotagMatchTags(path, r.Tag(), trimExt) if err != nil { return fmt.Errorf("autotag scraper viaScene: %w", err) } @@ -125,21 +126,24 @@ func (s autotagScraper) viaGallery(ctx context.Context, _client *http.Client, ga return nil, nil } + // only trim extension if gallery is file-based + trimExt := gallery.Zip + var ret *models.ScrapedGallery // populate performers, studio and tags based on scene path if err := s.txnManager.WithReadTxn(ctx, func(r models.ReaderRepository) error { path := gallery.Path.String - performers, err := autotagMatchPerformers(path, r.Performer()) + performers, err := autotagMatchPerformers(path, r.Performer(), trimExt) if err != nil { return fmt.Errorf("autotag scraper viaGallery: %w", err) } - studio, err := autotagMatchStudio(path, r.Studio()) + studio, err := autotagMatchStudio(path, r.Studio(), trimExt) if err != nil { return fmt.Errorf("autotag scraper viaGallery: %w", err) } - tags, err := autotagMatchTags(path, r.Tag()) + tags, err := autotagMatchTags(path, r.Tag(), trimExt) if err != nil { return fmt.Errorf("autotag scraper viaGallery: %w", err) } diff --git a/ui/v2.5/src/components/Changelog/versions/v0160.md b/ui/v2.5/src/components/Changelog/versions/v0160.md index 61a4dd282..bb0ed9efd 100644 --- a/ui/v2.5/src/components/Changelog/versions/v0160.md +++ b/ui/v2.5/src/components/Changelog/versions/v0160.md @@ -2,4 +2,6 @@ * Support submitting stash-box scene updates for scenes with stash ids. ([#2577](https://github.com/stashapp/stash/pull/2577)) ### 🐛 Bug fixes +* Fix folder-based galleries not auto-tagging correctly if folder name contains `.` characters. ([#2658](https://github.com/stashapp/stash/pull/2658)) +* Fix scene cover in scene edit panel not being updated when changing scenes. ([#2657](https://github.com/stashapp/stash/pull/2657)) * Fix moved gallery zip files not being rescanned. ([#2611](https://github.com/stashapp/stash/pull/2611)) \ No newline at end of file