diff --git a/internal/api/changeset_translator.go b/internal/api/changeset_translator.go index 5c81c12cb..45285bdde 100644 --- a/internal/api/changeset_translator.go +++ b/internal/api/changeset_translator.go @@ -98,7 +98,7 @@ func (t changesetTranslator) string(value *string) string { return "" } - return *value + return strings.TrimSpace(*value) } func (t changesetTranslator) optionalString(value *string, field string) models.OptionalString { @@ -106,7 +106,12 @@ func (t changesetTranslator) optionalString(value *string, field string) models. return models.OptionalString{} } - return models.NewOptionalStringPtr(value) + if value == nil { + return models.NewOptionalStringPtr(nil) + } + + trimmed := strings.TrimSpace(*value) + return models.NewOptionalString(trimmed) } func (t changesetTranslator) optionalDate(value *string, field string) (models.OptionalDate, error) { @@ -318,8 +323,14 @@ func (t changesetTranslator) updateStrings(value []string, field string) *models return nil } + // Trim whitespace from each string + trimmedValues := make([]string, len(value)) + for i, v := range value { + trimmedValues[i] = strings.TrimSpace(v) + } + return &models.UpdateStrings{ - Values: value, + Values: trimmedValues, Mode: models.RelationshipUpdateModeSet, } } @@ -329,8 +340,14 @@ func (t changesetTranslator) updateStringsBulk(value *BulkUpdateStrings, field s return nil } + // Trim whitespace from each string + trimmedValues := make([]string, len(value.Values)) + for i, v := range value.Values { + trimmedValues[i] = strings.TrimSpace(v) + } + return &models.UpdateStrings{ - Values: value.Values, + Values: trimmedValues, Mode: value.Mode, } } @@ -448,7 +465,7 @@ func groupsDescriptionsFromGroupInput(input []*GroupDescriptionInput) ([]models. GroupID: gID, } if v.Description != nil { - ret[i].Description = *v.Description + ret[i].Description = strings.TrimSpace(*v.Description) } } diff --git a/internal/api/resolver_mutation_gallery.go b/internal/api/resolver_mutation_gallery.go index db6862274..2ff9e8eb5 100644 --- a/internal/api/resolver_mutation_gallery.go +++ b/internal/api/resolver_mutation_gallery.go @@ -6,6 +6,7 @@ import ( "fmt" "os" "strconv" + "strings" "github.com/stashapp/stash/internal/manager" "github.com/stashapp/stash/pkg/file" @@ -43,7 +44,7 @@ func (r *mutationResolver) GalleryCreate(ctx context.Context, input GalleryCreat // Populate a new gallery from the input newGallery := models.NewGallery() - newGallery.Title = input.Title + newGallery.Title = strings.TrimSpace(input.Title) newGallery.Code = translator.string(input.Code) newGallery.Details = translator.string(input.Details) newGallery.Photographer = translator.string(input.Photographer) @@ -74,9 +75,9 @@ func (r *mutationResolver) GalleryCreate(ctx context.Context, input GalleryCreat } if input.Urls != nil { - newGallery.URLs = models.NewRelatedStrings(input.Urls) + newGallery.URLs = models.NewRelatedStrings(stringslice.TrimSpace(input.Urls)) } else if input.URL != nil { - newGallery.URLs = models.NewRelatedStrings([]string{*input.URL}) + newGallery.URLs = models.NewRelatedStrings([]string{strings.TrimSpace(*input.URL)}) } // Start the transaction and save the gallery diff --git a/internal/api/resolver_mutation_group.go b/internal/api/resolver_mutation_group.go index d75994d14..14dc817b9 100644 --- a/internal/api/resolver_mutation_group.go +++ b/internal/api/resolver_mutation_group.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "strconv" + "strings" "github.com/stashapp/stash/internal/static" "github.com/stashapp/stash/pkg/group" @@ -21,7 +22,7 @@ func groupFromGroupCreateInput(ctx context.Context, input GroupCreateInput) (*mo // Populate a new group from the input newGroup := models.NewGroup() - newGroup.Name = input.Name + newGroup.Name = strings.TrimSpace(input.Name) newGroup.Aliases = translator.string(input.Aliases) newGroup.Duration = input.Duration newGroup.Rating = input.Rating100 @@ -55,7 +56,7 @@ func groupFromGroupCreateInput(ctx context.Context, input GroupCreateInput) (*mo } if input.Urls != nil { - newGroup.URLs = models.NewRelatedStrings(input.Urls) + newGroup.URLs = models.NewRelatedStrings(stringslice.TrimSpace(input.Urls)) } return &newGroup, nil diff --git a/internal/api/resolver_mutation_movie.go b/internal/api/resolver_mutation_movie.go index 2e1011083..cb19e540f 100644 --- a/internal/api/resolver_mutation_movie.go +++ b/internal/api/resolver_mutation_movie.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "strconv" + "strings" "github.com/stashapp/stash/internal/static" "github.com/stashapp/stash/pkg/models" @@ -32,7 +33,7 @@ func (r *mutationResolver) MovieCreate(ctx context.Context, input MovieCreateInp // Populate a new group from the input newGroup := models.NewGroup() - newGroup.Name = input.Name + newGroup.Name = strings.TrimSpace(input.Name) newGroup.Aliases = translator.string(input.Aliases) newGroup.Duration = input.Duration newGroup.Rating = input.Rating100 @@ -56,9 +57,9 @@ func (r *mutationResolver) MovieCreate(ctx context.Context, input MovieCreateInp } if input.Urls != nil { - newGroup.URLs = models.NewRelatedStrings(input.Urls) + newGroup.URLs = models.NewRelatedStrings(stringslice.TrimSpace(input.Urls)) } else if input.URL != nil { - newGroup.URLs = models.NewRelatedStrings([]string{*input.URL}) + newGroup.URLs = models.NewRelatedStrings([]string{strings.TrimSpace(*input.URL)}) } // Process the base 64 encoded image string diff --git a/internal/api/resolver_mutation_performer.go b/internal/api/resolver_mutation_performer.go index 47b02147d..15fb5056a 100644 --- a/internal/api/resolver_mutation_performer.go +++ b/internal/api/resolver_mutation_performer.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "strconv" + "strings" "github.com/stashapp/stash/pkg/models" "github.com/stashapp/stash/pkg/performer" @@ -37,9 +38,9 @@ func (r *mutationResolver) PerformerCreate(ctx context.Context, input models.Per // Populate a new performer from the input newPerformer := models.NewPerformer() - newPerformer.Name = input.Name + newPerformer.Name = strings.TrimSpace(input.Name) newPerformer.Disambiguation = translator.string(input.Disambiguation) - newPerformer.Aliases = models.NewRelatedStrings(input.AliasList) + newPerformer.Aliases = models.NewRelatedStrings(stringslice.TrimSpace(input.AliasList)) newPerformer.Gender = input.Gender newPerformer.Ethnicity = translator.string(input.Ethnicity) newPerformer.Country = translator.string(input.Country) @@ -62,17 +63,17 @@ func (r *mutationResolver) PerformerCreate(ctx context.Context, input models.Per newPerformer.URLs = models.NewRelatedStrings([]string{}) if input.URL != nil { - newPerformer.URLs.Add(*input.URL) + newPerformer.URLs.Add(strings.TrimSpace(*input.URL)) } if input.Twitter != nil { - newPerformer.URLs.Add(utils.URLFromHandle(*input.Twitter, twitterURL)) + newPerformer.URLs.Add(utils.URLFromHandle(strings.TrimSpace(*input.Twitter), twitterURL)) } if input.Instagram != nil { - newPerformer.URLs.Add(utils.URLFromHandle(*input.Instagram, instagramURL)) + newPerformer.URLs.Add(utils.URLFromHandle(strings.TrimSpace(*input.Instagram), instagramURL)) } if input.Urls != nil { - newPerformer.URLs.Add(input.Urls...) + newPerformer.URLs.Add(stringslice.TrimSpace(input.Urls)...) } var err error diff --git a/internal/api/resolver_mutation_saved_filter.go b/internal/api/resolver_mutation_saved_filter.go index e49c1214c..6e825e3d5 100644 --- a/internal/api/resolver_mutation_saved_filter.go +++ b/internal/api/resolver_mutation_saved_filter.go @@ -32,7 +32,7 @@ func (r *mutationResolver) SaveFilter(ctx context.Context, input SaveFilterInput f := models.SavedFilter{ Mode: input.Mode, - Name: input.Name, + Name: strings.TrimSpace(input.Name), FindFilter: input.FindFilter, ObjectFilter: input.ObjectFilter, UIOptions: input.UIOptions, diff --git a/internal/api/resolver_mutation_scene.go b/internal/api/resolver_mutation_scene.go index ae5903112..c08184add 100644 --- a/internal/api/resolver_mutation_scene.go +++ b/internal/api/resolver_mutation_scene.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "strconv" + "strings" "time" "github.com/stashapp/stash/internal/manager" @@ -62,9 +63,9 @@ func (r *mutationResolver) SceneCreate(ctx context.Context, input models.SceneCr } if input.Urls != nil { - newScene.URLs = models.NewRelatedStrings(input.Urls) + newScene.URLs = models.NewRelatedStrings(stringslice.TrimSpace(input.Urls)) } else if input.URL != nil { - newScene.URLs = models.NewRelatedStrings([]string{*input.URL}) + newScene.URLs = models.NewRelatedStrings([]string{strings.TrimSpace(*input.URL)}) } newScene.PerformerIDs, err = translator.relatedIds(input.PerformerIds) @@ -653,7 +654,7 @@ func (r *mutationResolver) SceneMarkerCreate(ctx context.Context, input SceneMar // Populate a new scene marker from the input newMarker := models.NewSceneMarker() - newMarker.Title = input.Title + newMarker.Title = strings.TrimSpace(input.Title) newMarker.Seconds = input.Seconds newMarker.PrimaryTagID = primaryTagID newMarker.SceneID = sceneID diff --git a/internal/api/resolver_mutation_studio.go b/internal/api/resolver_mutation_studio.go index 03c13d85f..4b3316111 100644 --- a/internal/api/resolver_mutation_studio.go +++ b/internal/api/resolver_mutation_studio.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "strconv" + "strings" "github.com/stashapp/stash/pkg/models" "github.com/stashapp/stash/pkg/plugin/hook" @@ -32,23 +33,23 @@ func (r *mutationResolver) StudioCreate(ctx context.Context, input models.Studio // Populate a new studio from the input newStudio := models.NewStudio() - newStudio.Name = input.Name + newStudio.Name = strings.TrimSpace(input.Name) newStudio.Rating = input.Rating100 newStudio.Favorite = translator.bool(input.Favorite) newStudio.Details = translator.string(input.Details) newStudio.IgnoreAutoTag = translator.bool(input.IgnoreAutoTag) - newStudio.Aliases = models.NewRelatedStrings(input.Aliases) + newStudio.Aliases = models.NewRelatedStrings(stringslice.TrimSpace(input.Aliases)) newStudio.StashIDs = models.NewRelatedStashIDs(models.StashIDInputs(input.StashIds).ToStashIDs()) var err error newStudio.URLs = models.NewRelatedStrings([]string{}) if input.URL != nil { - newStudio.URLs.Add(*input.URL) + newStudio.URLs.Add(strings.TrimSpace(*input.URL)) } if input.Urls != nil { - newStudio.URLs.Add(input.Urls...) + newStudio.URLs.Add(stringslice.TrimSpace(input.Urls)...) } newStudio.ParentID, err = translator.intPtrFromString(input.ParentID) diff --git a/internal/api/resolver_mutation_tag.go b/internal/api/resolver_mutation_tag.go index 05d756acf..f8d4943be 100644 --- a/internal/api/resolver_mutation_tag.go +++ b/internal/api/resolver_mutation_tag.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "strconv" + "strings" "github.com/stashapp/stash/pkg/logger" "github.com/stashapp/stash/pkg/models" @@ -32,9 +33,9 @@ func (r *mutationResolver) TagCreate(ctx context.Context, input TagCreateInput) // Populate a new tag from the input newTag := models.NewTag() - newTag.Name = input.Name + newTag.Name = strings.TrimSpace(input.Name) newTag.SortName = translator.string(input.SortName) - newTag.Aliases = models.NewRelatedStrings(input.Aliases) + newTag.Aliases = models.NewRelatedStrings(stringslice.TrimSpace(input.Aliases)) newTag.Favorite = translator.bool(input.Favorite) newTag.Description = translator.string(input.Description) newTag.IgnoreAutoTag = translator.bool(input.IgnoreAutoTag) diff --git a/pkg/models/model_scraped_item.go b/pkg/models/model_scraped_item.go index 417564db5..d4e849e11 100644 --- a/pkg/models/model_scraped_item.go +++ b/pkg/models/model_scraped_item.go @@ -30,7 +30,7 @@ func (ScrapedStudio) IsScrapedContent() {} func (s *ScrapedStudio) ToStudio(endpoint string, excluded map[string]bool) *Studio { // Populate a new studio from the input ret := NewStudio() - ret.Name = s.Name + ret.Name = strings.TrimSpace(s.Name) if s.RemoteSiteID != nil && endpoint != "" { ret.StashIDs = NewRelatedStashIDs([]StashID{ @@ -95,37 +95,38 @@ func (s *ScrapedStudio) ToPartial(id string, endpoint string, excluded map[strin currentTime := time.Now() if s.Name != "" && !excluded["name"] { - ret.Name = NewOptionalString(s.Name) + ret.Name = NewOptionalString(strings.TrimSpace(s.Name)) } if len(s.URLs) > 0 { if !excluded["urls"] { + ret.URLs = &UpdateStrings{ - Values: s.URLs, + Values: stringslice.TrimSpace(s.URLs), Mode: RelationshipUpdateModeSet, } } } else { urls := []string{} if s.URL != nil && !excluded["url"] { - urls = append(urls, *s.URL) + urls = append(urls, strings.TrimSpace(*s.URL)) } if len(urls) > 0 { ret.URLs = &UpdateStrings{ - Values: urls, + Values: stringslice.TrimSpace(urls), Mode: RelationshipUpdateModeSet, } } } if s.Details != nil && !excluded["details"] { - ret.Details = NewOptionalString(*s.Details) + ret.Details = NewOptionalString(strings.TrimSpace(*s.Details)) } if s.Aliases != nil && !excluded["aliases"] { ret.Aliases = &UpdateStrings{ - Values: stringslice.FromString(*s.Aliases, ","), + Values: stringslice.TrimSpace(stringslice.FromString(*s.Aliases, ",")), Mode: RelationshipUpdateModeSet, } } @@ -197,10 +198,14 @@ func (ScrapedPerformer) IsScrapedContent() {} func (p *ScrapedPerformer) ToPerformer(endpoint string, excluded map[string]bool) *Performer { ret := NewPerformer() currentTime := time.Now() - ret.Name = *p.Name + ret.Name = strings.TrimSpace(*p.Name) if p.Aliases != nil && !excluded["aliases"] { - ret.Aliases = NewRelatedStrings(stringslice.FromString(*p.Aliases, ",")) + aliases := stringslice.FromString(*p.Aliases, ",") + for i, alias := range aliases { + aliases[i] = strings.TrimSpace(alias) + } + ret.Aliases = NewRelatedStrings(aliases) } if p.Birthdate != nil && !excluded["birthdate"] { date, err := ParseDate(*p.Birthdate) diff --git a/pkg/sliceutil/stringslice/string_collections.go b/pkg/sliceutil/stringslice/string_collections.go index f6ea1361c..f5251de5f 100644 --- a/pkg/sliceutil/stringslice/string_collections.go +++ b/pkg/sliceutil/stringslice/string_collections.go @@ -44,3 +44,11 @@ func UniqueFold(s []string) []string { } return ret } + +// TrimSpace trims whitespace from each string in a slice. +func TrimSpace(s []string) []string { + for i, v := range s { + s[i] = strings.TrimSpace(v) + } + return s +}