diff --git a/graphql/schema/schema.graphql b/graphql/schema/schema.graphql index 6673a6e40..91c9a3640 100644 --- a/graphql/schema/schema.graphql +++ b/graphql/schema/schema.graphql @@ -1,5 +1,3 @@ -# TODO(audio): add audioCreate, audioUpdate, audioDestroy, audiosDestroy - "The query root for this schema" type Query { # Filters diff --git a/graphql/schema/types/audio.graphql b/graphql/schema/types/audio.graphql index 100395356..ae761239f 100644 --- a/graphql/schema/types/audio.graphql +++ b/graphql/schema/types/audio.graphql @@ -47,8 +47,6 @@ type Audio { files: [AudioFile!]! paths: AudioPathsType! # Resolver - # TODO(future|audio_markers): add in audio markers - # audio_markers: [AudioMarker!]! studio: Studio groups: [AudioGroup!]! tags: [Tag!]! diff --git a/graphql/schema/types/file.graphql b/graphql/schema/types/file.graphql index 2db611aa4..050315374 100644 --- a/graphql/schema/types/file.graphql +++ b/graphql/schema/types/file.graphql @@ -125,7 +125,6 @@ type ImageFile implements BaseFile { union VisualFile = VideoFile | ImageFile type AudioFile implements BaseFile { - # TODO(audio): edit this id: ID! path: String! basename: String! diff --git a/internal/api/resolver_query_find_audio.go b/internal/api/resolver_query_find_audio.go index 9ea1a900e..89daf19c0 100644 --- a/internal/api/resolver_query_find_audio.go +++ b/internal/api/resolver_query_find_audio.go @@ -1,5 +1,3 @@ -// TODO(audio): update this file - package api import ( diff --git a/internal/identify/identify.go b/internal/identify/identify.go index 847f284e1..6dc67dac3 100644 --- a/internal/identify/identify.go +++ b/internal/identify/identify.go @@ -1,4 +1,3 @@ -// TODO(audio): update this file // Package identify provides the scene identification functionality for the application. // The identify functionality uses scene scrapers to identify a given scene and // set its metadata based on the scraped data. diff --git a/internal/manager/task_scan.go b/internal/manager/task_scan.go index 66b9b6b19..6dbb466ae 100644 --- a/internal/manager/task_scan.go +++ b/internal/manager/task_scan.go @@ -712,7 +712,7 @@ func getScanHandlers(options ScanMetadataInput, taskQueue *job.TaskQueue, progre CreatorUpdater: r.Audio, CaptionUpdater: r.File, PluginCache: pluginCache, - FileNamingAlgorithm: c.GetVideoFileNamingAlgorithm(), + FileNamingAlgorithm: c.GetAudioFileNamingAlgorithm(), Paths: mgr.Paths, }, }, diff --git a/pkg/audio/delete.go b/pkg/audio/delete.go index 54c3cb555..5218d31ff 100644 --- a/pkg/audio/delete.go +++ b/pkg/audio/delete.go @@ -7,7 +7,6 @@ import ( "path/filepath" "github.com/stashapp/stash/pkg/file" - file_audio "github.com/stashapp/stash/pkg/file/audio" "github.com/stashapp/stash/pkg/fsutil" "github.com/stashapp/stash/pkg/logger" "github.com/stashapp/stash/pkg/models" @@ -96,17 +95,6 @@ func (s *Service) deleteFiles(ctx context.Context, audio *models.Audio, fileDele if err := file.Destroy(ctx, s.File, f, fileDeleter.Deleter, deleteFile); err != nil { return err } - - // don't delete files in zip archives - if f.ZipFileID == nil { - funscriptPath := file_audio.GetFunscriptPath(f.Path) - funscriptExists, _ := fsutil.FileExists(funscriptPath) - if funscriptExists { - if err := fileDeleter.Files([]string{funscriptPath}); err != nil { - return err - } - } - } } return nil diff --git a/pkg/audio/export.go b/pkg/audio/export.go index 8b53838bc..71f0d6ead 100644 --- a/pkg/audio/export.go +++ b/pkg/audio/export.go @@ -6,7 +6,6 @@ import ( "context" "fmt" "math" - "strconv" "github.com/stashapp/stash/pkg/models" "github.com/stashapp/stash/pkg/models/json" @@ -171,18 +170,6 @@ func GetDependentGroupIDs(ctx context.Context, audio *models.Audio) ([]int, erro return ret, nil } -func getDecimalString(num float64) string { - if num == 0 { - return "" - } - - precision := getPrecision(num) - if precision == 0 { - precision = 1 - } - return fmt.Sprintf("%."+strconv.Itoa(precision)+"f", num) -} - func getPrecision(num float64) int { if num == 0 { return 0 diff --git a/pkg/audio/export_test.go b/pkg/audio/export_test.go index f01b8f6a9..bdaad0a95 100644 --- a/pkg/audio/export_test.go +++ b/pkg/audio/export_test.go @@ -32,11 +32,7 @@ const ( noGroupsID = 13 errFindGroupID = 15 - noMarkersID = 16 - errMarkersID = 17 - errFindPrimaryTagID = 18 - errFindByMarkerID = 19 - errCustomFieldsID = 20 + errCustomFieldsID = 20 ) var ( diff --git a/pkg/audio/filename_parser.go b/pkg/audio/filename_parser.go deleted file mode 100644 index cf0e0be22..000000000 --- a/pkg/audio/filename_parser.go +++ /dev/null @@ -1,722 +0,0 @@ -// TODO(audio): update this file - -package audio - -import ( - "context" - "errors" - "path/filepath" - "regexp" - "strconv" - "strings" - "time" - - "github.com/stashapp/stash/pkg/studio" - - "github.com/stashapp/stash/pkg/models" - "github.com/stashapp/stash/pkg/tag" -) - -type parserField struct { - field string - fieldRegex *regexp.Regexp - regex string - isFullDateField bool - isCaptured bool -} - -func newParserField(field string, regex string, captured bool) parserField { - ret := parserField{ - field: field, - isFullDateField: false, - isCaptured: captured, - } - - ret.fieldRegex, _ = regexp.Compile(`\{` + ret.field + `\}`) - - regexStr := regex - - if captured { - regexStr = "(" + regexStr + ")" - } - ret.regex = regexStr - - return ret -} - -func newFullDateParserField(field string, regex string) parserField { - ret := newParserField(field, regex, true) - ret.isFullDateField = true - return ret -} - -func (f parserField) replaceInPattern(pattern string) string { - return string(f.fieldRegex.ReplaceAllString(pattern, f.regex)) -} - -var validFields map[string]parserField -var escapeCharRE *regexp.Regexp -var capitalizeTitleRE *regexp.Regexp -var multiWSRE *regexp.Regexp -var delimiterRE *regexp.Regexp - -func compileREs() { - const escapeCharPattern = `([\-\.\(\)\[\]])` - escapeCharRE = regexp.MustCompile(escapeCharPattern) - - const capitaliseTitlePattern = `(?:^| )\w` - capitalizeTitleRE = regexp.MustCompile(capitaliseTitlePattern) - - const multiWSPattern = ` {2,}` - multiWSRE = regexp.MustCompile(multiWSPattern) - - const delimiterPattern = `(?:\.|-|_)` - delimiterRE = regexp.MustCompile(delimiterPattern) -} - -func initParserFields() { - if validFields != nil { - return - } - - ret := make(map[string]parserField) - - ret["title"] = newParserField("title", ".*", true) - ret["ext"] = newParserField("ext", ".*$", false) - - ret["d"] = newParserField("d", `(?:\.|-|_)`, false) - ret["rating"] = newParserField("rating", `\d`, true) - ret["rating100"] = newParserField("rating100", `\d`, true) - ret["performer"] = newParserField("performer", ".*", true) - ret["studio"] = newParserField("studio", ".*", true) - ret["movie"] = newParserField("movie", ".*", true) - ret["tag"] = newParserField("tag", ".*", true) - - // date fields - ret["date"] = newParserField("date", `\d{4}-\d{2}-\d{2}`, true) - ret["yyyy"] = newParserField("yyyy", `\d{4}`, true) - ret["yy"] = newParserField("yy", `\d{2}`, true) - ret["mm"] = newParserField("mm", `\d{2}`, true) - ret["mmm"] = newParserField("mmm", `\w{3}`, true) - ret["dd"] = newParserField("dd", `\d{2}`, true) - ret["yyyymmdd"] = newFullDateParserField("yyyymmdd", `\d{8}`) - ret["yymmdd"] = newFullDateParserField("yymmdd", `\d{6}`) - ret["ddmmyyyy"] = newFullDateParserField("ddmmyyyy", `\d{8}`) - ret["ddmmyy"] = newFullDateParserField("ddmmyy", `\d{6}`) - ret["mmddyyyy"] = newFullDateParserField("mmddyyyy", `\d{8}`) - ret["mmddyy"] = newFullDateParserField("mmddyy", `\d{6}`) - - validFields = ret -} - -func replacePatternWithRegex(pattern string, ignoreWords []string) string { - initParserFields() - - for _, field := range validFields { - pattern = field.replaceInPattern(pattern) - } - - ignoreClause := getIgnoreClause(ignoreWords) - ignoreField := newParserField("i", ignoreClause, false) - pattern = ignoreField.replaceInPattern(pattern) - - return pattern -} - -type parseMapper struct { - fields []string - regexString string - regex *regexp.Regexp -} - -func getIgnoreClause(ignoreFields []string) string { - if len(ignoreFields) == 0 { - return "" - } - - var ignoreClauses []string - - for _, v := range ignoreFields { - newVal := string(escapeCharRE.ReplaceAllString(v, `\$1`)) - newVal = strings.TrimSpace(newVal) - newVal = "(?:" + newVal + ")" - ignoreClauses = append(ignoreClauses, newVal) - } - - return "(?:" + strings.Join(ignoreClauses, "|") + ")" -} - -func newParseMapper(pattern string, ignoreFields []string) (*parseMapper, error) { - ret := &parseMapper{} - - // escape control characters - regex := escapeCharRE.ReplaceAllString(pattern, `\$1`) - - // replace {} with wildcard - braceRE := regexp.MustCompile(`\{\}`) - regex = braceRE.ReplaceAllString(regex, ".*") - - // replace all known fields with applicable regexes - regex = replacePatternWithRegex(regex, ignoreFields) - - ret.regexString = regex - - // make case insensitive - regex = "(?i)" + regex - - var err error - - ret.regex, err = regexp.Compile(regex) - - if err != nil { - return nil, err - } - - // find invalid fields - invalidRE := regexp.MustCompile(`\{[A-Za-z]+\}`) - foundInvalid := invalidRE.FindAllString(regex, -1) - if len(foundInvalid) > 0 { - return nil, errors.New("Invalid fields: " + strings.Join(foundInvalid, ", ")) - } - - fieldExtractor := regexp.MustCompile(`\{([A-Za-z]+)\}`) - - result := fieldExtractor.FindAllStringSubmatch(pattern, -1) - - var fields []string - for _, v := range result { - field := v[1] - - // only add to fields if it is captured - parserField, found := validFields[field] - if found && parserField.isCaptured { - fields = append(fields, field) - } - } - - ret.fields = fields - - return ret, nil -} - -type audioHolder struct { - audio *models.Audio - result *models.Audio - yyyy string - mm string - dd string - performers []string - groups []string - studio string - tags []string -} - -func newAudioHolder(audio *models.Audio) *audioHolder { - audioCopy := models.Audio{ - ID: audio.ID, - Files: audio.Files, - // Checksum: audio.Checksum, - // Path: audio.Path, - } - ret := audioHolder{ - audio: audio, - result: &audioCopy, - } - - return &ret -} - -func validateRating(rating int) bool { - return rating >= 1 && rating <= 5 -} - -func validateRating100(rating100 int) bool { - return rating100 >= 1 && rating100 <= 100 -} - -// returns nil if invalid -func parseDate(dateStr string) *models.Date { - splits := strings.Split(dateStr, "-") - if len(splits) != 3 { - return nil - } - - year, _ := strconv.Atoi(splits[0]) - month, _ := strconv.Atoi(splits[1]) - d, _ := strconv.Atoi(splits[2]) - - // assume year must be between 1900 and 2100 - if year < 1900 || year > 2100 { - return nil - } - - if month < 1 || month > 12 { - return nil - } - - // not checking individual months to ensure date is in the correct range - if d < 1 || d > 31 { - return nil - } - - ret, err := models.ParseDate(dateStr) - if err != nil { - return nil - } - return &ret -} - -func (h *audioHolder) setDate(field *parserField, value string) { - yearIndex := 0 - yearLength := len(strings.Split(field.field, "y")) - 1 - dateIndex := 0 - monthIndex := 0 - - switch field.field { - case "yyyymmdd", "yymmdd": - monthIndex = yearLength - dateIndex = monthIndex + 2 - case "ddmmyyyy", "ddmmyy": - monthIndex = 2 - yearIndex = monthIndex + 2 - case "mmddyyyy", "mmddyy": - dateIndex = monthIndex + 2 - yearIndex = dateIndex + 2 - } - - yearValue := value[yearIndex : yearIndex+yearLength] - monthValue := value[monthIndex : monthIndex+2] - dateValue := value[dateIndex : dateIndex+2] - - fullDate := yearValue + "-" + monthValue + "-" + dateValue - - // ensure the date is valid - // only set if new value is different from the old - newDate := parseDate(fullDate) - if newDate != nil && h.audio.Date != nil && *h.audio.Date != *newDate { - h.result.Date = newDate - } -} - -func mmmToMonth(mmm string) string { - format := "02-Jan-2006" - dateStr := "01-" + mmm + "-2000" - t, err := time.Parse(format, dateStr) - - if err != nil { - return "" - } - - // expect month in two-digit format - format = "01-02-2006" - return t.Format(format)[0:2] -} - -func (h *audioHolder) setField(field parserField, value interface{}) { - if field.isFullDateField { - h.setDate(&field, value.(string)) - return - } - - switch field.field { - case "title": - v := value.(string) - h.result.Title = v - case "date": - h.result.Date = parseDate(value.(string)) - case "rating": - rating, _ := strconv.Atoi(value.(string)) - if validateRating(rating) { - // convert to 1-100 scale - rating = models.Rating5To100(rating) - h.result.Rating = &rating - } - case "rating100": - rating, _ := strconv.Atoi(value.(string)) - if validateRating100(rating) { - h.result.Rating = &rating - } - case "performer": - // add performer to list - h.performers = append(h.performers, value.(string)) - case "studio": - h.studio = value.(string) - case "movie": - h.groups = append(h.groups, value.(string)) - case "tag": - h.tags = append(h.tags, value.(string)) - case "yyyy": - h.yyyy = value.(string) - case "yy": - v := value.(string) - v = "20" + v - h.yyyy = v - case "mmm": - h.mm = mmmToMonth(value.(string)) - case "mm": - h.mm = value.(string) - case "dd": - h.dd = value.(string) - } -} - -func (h *audioHolder) postParse() { - // set the date if the components are set - if h.yyyy != "" && h.mm != "" && h.dd != "" { - fullDate := h.yyyy + "-" + h.mm + "-" + h.dd - h.setField(validFields["date"], fullDate) - } -} - -func (m parseMapper) parse(audio *models.Audio) *audioHolder { - - // #302 - if the pattern includes a path separator, then include the entire - // audio path in the match. Otherwise, use the default behaviour of just - // the file's basename - // must be double \ because of the regex escaping - filename := filepath.Base(audio.Path) - if strings.Contains(m.regexString, `\\`) || strings.Contains(m.regexString, "/") { - filename = audio.Path - } - - result := m.regex.FindStringSubmatch(filename) - - if len(result) == 0 { - return nil - } - - initParserFields() - - audioHolder := newAudioHolder(audio) - - for index, match := range result { - if index == 0 { - // skip entire match - continue - } - - field := m.fields[index-1] - parserField, found := validFields[field] - if found { - audioHolder.setField(parserField, match) - } - } - - audioHolder.postParse() - - return audioHolder -} - -type FilenameParser struct { - Pattern string - ParserInput models.AudioParserInput - Filter *models.FindFilterType - whitespaceRE *regexp.Regexp - repository FilenameParserRepository - performerCache map[string]*models.Performer - studioCache map[string]*models.Studio - groupCache map[string]*models.Group - tagCache map[string]*models.Tag -} - -func NewFilenameParser(filter *models.FindFilterType, config models.AudioParserInput, repo FilenameParserRepository) *FilenameParser { - p := &FilenameParser{ - Pattern: *filter.Q, - ParserInput: config, - Filter: filter, - repository: repo, - } - - p.performerCache = make(map[string]*models.Performer) - p.studioCache = make(map[string]*models.Studio) - p.groupCache = make(map[string]*models.Group) - p.tagCache = make(map[string]*models.Tag) - - p.initWhiteSpaceRegex() - - return p -} - -func (p *FilenameParser) initWhiteSpaceRegex() { - compileREs() - - wsChars := "" - if p.ParserInput.WhitespaceCharacters != nil { - wsChars = *p.ParserInput.WhitespaceCharacters - wsChars = strings.TrimSpace(wsChars) - } - - if len(wsChars) > 0 { - wsRegExp := escapeCharRE.ReplaceAllString(wsChars, `\$1`) - wsRegExp = "[" + wsRegExp + "]" - p.whitespaceRE = regexp.MustCompile(wsRegExp) - } -} - -type FilenameParserRepository struct { - Audio models.AudioQueryer - Performer PerformerNamesFinder - Studio models.StudioQueryer - Group GroupNameFinder - Tag models.TagNameFinder -} - -func NewFilenameParserRepository(repo models.Repository) FilenameParserRepository { - return FilenameParserRepository{ - Audio: repo.Audio, - Performer: repo.Performer, - Studio: repo.Studio, - Group: repo.Group, - Tag: repo.Tag, - } -} - -func (p *FilenameParser) Parse(ctx context.Context) ([]*models.AudioParserResult, int, error) { - // perform the query to find the audios - mapper, err := newParseMapper(p.Pattern, p.ParserInput.IgnoreWords) - - if err != nil { - return nil, 0, err - } - - audioFilter := &models.AudioFilterType{ - Path: &models.StringCriterionInput{ - Modifier: models.CriterionModifierMatchesRegex, - Value: "(?i)" + mapper.regexString, - }, - } - - if p.ParserInput.IgnoreOrganized != nil && *p.ParserInput.IgnoreOrganized { - organized := false - audioFilter.Organized = &organized - } - - p.Filter.Q = nil - - audios, total, err := QueryWithCount(ctx, p.repository.Audio, audioFilter, p.Filter) - if err != nil { - return nil, 0, err - } - - ret := p.parseAudios(ctx, audios, mapper) - - return ret, total, nil -} - -func (p *FilenameParser) parseAudios(ctx context.Context, audios []*models.Audio, mapper *parseMapper) []*models.AudioParserResult { - var ret []*models.AudioParserResult - for _, audio := range audios { - audioHolder := mapper.parse(audio) - - if audioHolder != nil { - r := &models.AudioParserResult{ - Audio: audio, - } - p.setParserResult(ctx, *audioHolder, r) - - ret = append(ret, r) - } - } - - return ret -} - -func (p FilenameParser) replaceWhitespaceCharacters(value string) string { - if p.whitespaceRE != nil { - value = p.whitespaceRE.ReplaceAllString(value, " ") - // remove consecutive spaces - value = multiWSRE.ReplaceAllString(value, " ") - } - - return value -} - -type PerformerNamesFinder interface { - FindByNames(ctx context.Context, names []string, nocase bool) ([]*models.Performer, error) -} - -func (p *FilenameParser) queryPerformer(ctx context.Context, qb PerformerNamesFinder, performerName string) *models.Performer { - // massage the performer name - performerName = delimiterRE.ReplaceAllString(performerName, " ") - - // check cache first - if ret, found := p.performerCache[performerName]; found { - return ret - } - - // perform an exact match and grab the first - performers, _ := qb.FindByNames(ctx, []string{performerName}, true) - - var ret *models.Performer - if len(performers) > 0 { - ret = performers[0] - } - - // add result to cache - p.performerCache[performerName] = ret - - return ret -} - -func (p *FilenameParser) queryStudio(ctx context.Context, qb models.StudioQueryer, studioName string) *models.Studio { - // massage the performer name - studioName = delimiterRE.ReplaceAllString(studioName, " ") - - // check cache first - if ret, found := p.studioCache[studioName]; found { - return ret - } - - ret, _ := studio.ByName(ctx, qb, studioName) - - // try to match on alias - if ret == nil { - ret, _ = studio.ByAlias(ctx, qb, studioName) - } - - // add result to cache - p.studioCache[studioName] = ret - - return ret -} - -type GroupNameFinder interface { - FindByName(ctx context.Context, name string, nocase bool) (*models.Group, error) -} - -func (p *FilenameParser) queryGroup(ctx context.Context, qb GroupNameFinder, groupName string) *models.Group { - // massage the group name - groupName = delimiterRE.ReplaceAllString(groupName, " ") - - // check cache first - if ret, found := p.groupCache[groupName]; found { - return ret - } - - ret, _ := qb.FindByName(ctx, groupName, true) - - // add result to cache - p.groupCache[groupName] = ret - - return ret -} - -func (p *FilenameParser) queryTag(ctx context.Context, qb models.TagNameFinder, tagName string) *models.Tag { - // massage the tag name - tagName = delimiterRE.ReplaceAllString(tagName, " ") - - // check cache first - if ret, found := p.tagCache[tagName]; found { - return ret - } - - // match tag name exactly - ret, _ := tag.ByName(ctx, qb, tagName) - - // try to match on alias - if ret == nil { - ret, _ = tag.ByAlias(ctx, qb, tagName) - } - - // add result to cache - p.tagCache[tagName] = ret - - return ret -} - -func (p *FilenameParser) setPerformers(ctx context.Context, qb PerformerNamesFinder, h audioHolder, result *models.AudioParserResult) { - // query for each performer - performersSet := make(map[int]bool) - for _, performerName := range h.performers { - if performerName != "" { - performer := p.queryPerformer(ctx, qb, performerName) - if performer != nil { - if _, found := performersSet[performer.ID]; !found { - result.PerformerIds = append(result.PerformerIds, strconv.Itoa(performer.ID)) - performersSet[performer.ID] = true - } - } - } - } -} - -func (p *FilenameParser) setTags(ctx context.Context, qb models.TagNameFinder, h audioHolder, result *models.AudioParserResult) { - // query for each performer - tagsSet := make(map[int]bool) - for _, tagName := range h.tags { - if tagName != "" { - tag := p.queryTag(ctx, qb, tagName) - if tag != nil { - if _, found := tagsSet[tag.ID]; !found { - result.TagIds = append(result.TagIds, strconv.Itoa(tag.ID)) - tagsSet[tag.ID] = true - } - } - } - } -} - -func (p *FilenameParser) setStudio(ctx context.Context, qb models.StudioQueryer, h audioHolder, result *models.AudioParserResult) { - // query for each performer - if h.studio != "" { - studio := p.queryStudio(ctx, qb, h.studio) - if studio != nil { - studioID := strconv.Itoa(studio.ID) - result.StudioID = &studioID - } - } -} - -func (p *FilenameParser) setGroups(ctx context.Context, qb GroupNameFinder, h audioHolder, result *models.AudioParserResult) { - // query for each group - groupsSet := make(map[int]bool) - for _, groupName := range h.groups { - if groupName != "" { - group := p.queryGroup(ctx, qb, groupName) - if group != nil { - if _, found := groupsSet[group.ID]; !found { - result.Groups = append(result.Groups, &models.AudioGroupID{ - GroupID: strconv.Itoa(group.ID), - }) - groupsSet[group.ID] = true - } - } - } - } -} - -func (p *FilenameParser) setParserResult(ctx context.Context, h audioHolder, result *models.AudioParserResult) { - if h.result.Title != "" { - title := h.result.Title - title = p.replaceWhitespaceCharacters(title) - - if p.ParserInput.CapitalizeTitle != nil && *p.ParserInput.CapitalizeTitle { - title = capitalizeTitleRE.ReplaceAllStringFunc(title, strings.ToUpper) - } - - result.Title = &title - } - - if h.result.Date != nil { - dateStr := h.result.Date.String() - result.Date = &dateStr - } - - if h.result.Rating != nil { - result.Rating = h.result.Rating - } - - r := p.repository - - if len(h.performers) > 0 { - p.setPerformers(ctx, r.Performer, h, result) - } - if len(h.tags) > 0 { - p.setTags(ctx, r.Tag, h, result) - } - p.setStudio(ctx, r.Studio, h, result) - - if len(h.groups) > 0 { - p.setGroups(ctx, r.Group, h, result) - } -} diff --git a/pkg/audio/fingerprints.go b/pkg/audio/fingerprints.go index 8c9c6be80..9a0d2bd85 100644 --- a/pkg/audio/fingerprints.go +++ b/pkg/audio/fingerprints.go @@ -1,5 +1,3 @@ -// TODO(audio): update this file - package audio import ( diff --git a/pkg/audio/import.go b/pkg/audio/import.go index caf79b652..b4f36d42d 100644 --- a/pkg/audio/import.go +++ b/pkg/audio/import.go @@ -79,7 +79,6 @@ func (i *Importer) audioJSONToAudio(audioJSON jsonschema.Audio) models.Audio { Details: audioJSON.Details, PerformerIDs: models.NewRelatedIDs([]int{}), TagIDs: models.NewRelatedIDs([]int{}), - GalleryIDs: models.NewRelatedIDs([]int{}), Groups: models.NewRelatedGroupsAudio([]models.GroupsAudios{}), } diff --git a/pkg/audio/import_test.go b/pkg/audio/import_test.go index 97fcb1dd5..7c37374ae 100644 --- a/pkg/audio/import_test.go +++ b/pkg/audio/import_test.go @@ -92,7 +92,6 @@ func TestImporterPreImport(t *testing.T) { PlayDuration: playDuration, Files: models.NewRelatedAudioFiles([]*models.AudioFile{}), - GalleryIDs: models.NewRelatedIDs([]int{}), TagIDs: models.NewRelatedIDs([]int{}), PerformerIDs: models.NewRelatedIDs([]int{}), Groups: models.NewRelatedGroupsAudio([]models.GroupsAudios{}), diff --git a/pkg/audio/service.go b/pkg/audio/service.go index af24067ae..abedb8f32 100644 --- a/pkg/audio/service.go +++ b/pkg/audio/service.go @@ -1,5 +1,3 @@ -// TODO(audio): update this file - // Package audio provides the application logic for audio functionality. // Most functionality is provided by [Service]. package audio diff --git a/pkg/file/audio/funscript.go b/pkg/file/audio/funscript.go deleted file mode 100644 index 30d2447e3..000000000 --- a/pkg/file/audio/funscript.go +++ /dev/null @@ -1,15 +0,0 @@ -// TODO(audio): update this file -package audio - -import ( - "path/filepath" - "strings" -) - -// GetFunscriptPath returns the path of a file -// with the extension changed to .funscript -func GetFunscriptPath(path string) string { - ext := filepath.Ext(path) - fn := strings.TrimSuffix(path, ext) - return fn + ".funscript" -} diff --git a/pkg/file/audio/scan.go b/pkg/file/audio/scan.go index aa39fd317..c07320d4f 100644 --- a/pkg/file/audio/scan.go +++ b/pkg/file/audio/scan.go @@ -1,4 +1,3 @@ -// TODO(audio): update this file package audio import ( diff --git a/pkg/models/audio.go b/pkg/models/audio.go index e248e5c3b..2eb62ae62 100644 --- a/pkg/models/audio.go +++ b/pkg/models/audio.go @@ -1,5 +1,3 @@ -// TODO(audio): update this file - package models import "context" diff --git a/pkg/models/model_audio.go b/pkg/models/model_audio.go index 858bf3825..2d0c60692 100644 --- a/pkg/models/model_audio.go +++ b/pkg/models/model_audio.go @@ -16,7 +16,6 @@ type Audio struct { Title string `json:"title"` Code string `json:"code"` Details string `json:"details"` - Artists string `json:"artists"` Date *Date `json:"date"` // Rating expressed in 1-100 scale Rating *int `json:"rating"` @@ -40,7 +39,6 @@ type Audio struct { PlayDuration float64 `json:"play_duration"` URLs RelatedStrings `json:"urls"` - GalleryIDs RelatedIDs `json:"gallery_ids"` TagIDs RelatedIDs `json:"tag_ids"` PerformerIDs RelatedIDs `json:"performer_ids"` Groups RelatedGroupsAudio `json:"groups"` @@ -134,12 +132,6 @@ func (s *Audio) LoadPrimaryFile(ctx context.Context, l FileGetter) error { }) } -func (s *Audio) LoadGalleryIDs(ctx context.Context, l GalleryIDLoader) error { - return s.GalleryIDs.load(func() ([]int, error) { - return l.GetGalleryIDs(ctx, s.ID) - }) -} - func (s *Audio) LoadPerformerIDs(ctx context.Context, l PerformerIDLoader) error { return s.PerformerIDs.load(func() ([]int, error) { return l.GetPerformerIDs(ctx, s.ID) diff --git a/pkg/models/paths/paths_audio.go b/pkg/models/paths/paths_audio.go index 5d9424fab..2f58900a2 100644 --- a/pkg/models/paths/paths_audio.go +++ b/pkg/models/paths/paths_audio.go @@ -1,4 +1,3 @@ -// TODO(audio): update this file package paths import ( diff --git a/pkg/sqlite/performer.go b/pkg/sqlite/performer.go index 57125a7b6..59a0f0e1e 100644 --- a/pkg/sqlite/performer.go +++ b/pkg/sqlite/performer.go @@ -744,6 +744,8 @@ var selectPerformerLatestSceneSQL = utils.StrFormat( }, ) +// TODO(audio): duplicate above for Audio + func (qb *PerformerStore) sortByLatestScene(direction string) string { // need to get the latest date from scenes return " ORDER BY (" + selectPerformerLatestSceneSQL + ") " + direction diff --git a/pkg/sqlite/studio.go b/pkg/sqlite/studio.go index 87f905935..dbdea7cca 100644 --- a/pkg/sqlite/studio.go +++ b/pkg/sqlite/studio.go @@ -653,6 +653,8 @@ var selectStudioLatestSceneSQL = utils.StrFormat( }, ) +// TODO(audio): duplicate above for Audio + func (qb *StudioStore) sortByLatestScene(direction string) string { // need to get the latest date from scenes return " ORDER BY (" + selectStudioLatestSceneSQL + ") " + direction